加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
interface.py 63.80 KB
一键复制 编辑 原始数据 按行查看 历史
shan.li 提交于 2021-03-21 11:35 . backup
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406
import os
import random
import subprocess
import sys
import webbrowser
import cv2 as cv
import pandas as pd
from PyQt5.QtCore import Qt, QDate, QTimer, QRect, QLine, pyqtSignal
from PyQt5.QtGui import QPixmap, QPainter, QPen, QColor, QIcon, QPalette, QImage, QBrush, QTextCursor
from PyQt5.QtWidgets import QLabel, QMainWindow, QLCDNumber, QTableWidgetItem, QMessageBox, QFileDialog
from PyQt5.QtWidgets import QHeaderView, QAbstractItemView, QDialog
from PyQt5.uic import loadUiType
from sympy import symbols, Eq, solve
import DataBase
import set_map
import set_mysql
import aboutDialog
import contact
import attribute
use_database = True
map_show = True
mysql_info = ['127.0.0.1', 3306, 'root', 'lucky123']
map_mode = "realtime_condition"
road_width = 3
map_nodes = []
map_roads = []
map_threshold = []
road_crowd_data = []
road_flow_data = []
area_cross = {}
area_cross_phase = {}
area_cross_road = {}
ui, _ = loadUiType("resource/ui/interface.ui")
# 重写QLabel类,作为地图画布
class MyLabel(QLabel):
interInfoEmit = pyqtSignal(str)
roadInfoEmit = pyqtSignal(list)
start_point = False
end_point = True
update_timer = False
line_width = road_width
num = 0
x0, x1, x2 = 0, 0, 0
y0, y1, y2 = 0, 0, 0
start_node, dest_node = 0, 0
nodes, roads = [], []
road_info = []
operation_record = []
crowded_level = [
[0, 255, 0],
[255, 255, 0],
[255, 0, 0],
[165, 42, 42],
]
# 求解方程组,得到两条平行线
@staticmethod
def solve_new_line(a, b, c, d, e):
x1, y1, x2, y2 = symbols('x1 y1 x2 y2')
eqs = [
Eq((y1 - b) ** 2 + (x1 - a) ** 2, e ** 2),
Eq((y1 - b) * (d - b), (a - c) * (x1 - a)),
Eq((y2 - d) ** 2 + (x2 - c) ** 2, e ** 2),
Eq((y2 - d) * (d - b), (a - c) * (x2 - c)),
Eq((y2 - y1) * (c - a), (d - b) * (x2 - x1)),
]
result = solve(eqs, [x1, y1, x2, y2])
p0, p1 = result[0], result[1]
result[0] = list(map(round, [p0[0], p0[1], p0[2], p0[3]]))
result[1] = list(map(round, [p1[2], p1[3], p1[0], p1[1]]))
return result
# 选点模式下鼠标左键按下
def left_mouse(self, event):
x, y = event.x(), event.y()
pa = attribute.point_attribute()
result = pa.exec_()
if result == QDialog.Accepted:
is_cross, area_num, cross_num, phase_amount = pa.attribute
if is_cross:
info = "道路选点->鼠标左键按下,选中交叉口\n选中坐标: ({:<3d}, {:>3d})\n分配归属: 区域{} 路口{} 相位数目{}". \
format(x, y, area_num, cross_num, phase_amount)
else:
info = "道路选点->鼠标左键按下,选中普通点位\n选中坐标: ({:<3d}, {:>3d})\n". \
format(x, y)
self.interInfoEmit.emit(info)
self.num += 1
self.x0, self.y0 = x, y
node = [self.x0, self.y0, is_cross, area_num, cross_num, phase_amount]
self.nodes.append(node)
# 添加操作记录
self.operation_record.append([0, node])
# 立即更新绘图
self.update()
elif result == QDialog.Rejected:
self.interInfoEmit.emit("道路选点->鼠标左键按下,未确认\n选中坐标: ({:<3d}, {:>3d})".format(x, y))
# 选点模式下鼠标右键按下
def right_mouse(self, event):
x, y = event.x(), event.y()
# 已知选点超过2个,可以右键开始连接道路,否则无效
if self.num >= 2:
# 上次终点已按下并确认,当前起点未按下
if self.end_point and (not self.start_point):
# 获取点击坐标
self.x1, self.y1 = x, y
# 终点置0
self.x2, self.y2 = 0, 0
find = False
for i in range(len(self.nodes)):
condition1 = (abs(self.nodes[i][0] - self.x1) < 10)
condition2 = (abs(self.nodes[i][1] - self.y1) < 10)
if condition1 and condition2:
find = True
# 修正起点为已存在的结点
self.x1, self.y1 = self.nodes[i][0], self.nodes[i][1]
self.start_node = i + 1
info = "道路选点->鼠标右键按下,选中起点\n起点坐标: ({:<3d}, {:>3d})".format(self.x1, self.y1)
self.interInfoEmit.emit(info)
# 设置起点已按下并确认,终点未按下,
self.start_point = True
self.end_point = False
# 添加操作记录
self.operation_record.append([1, [self.x1, self.y1]])
# 立即更新绘图
self.update()
break
# 若选中的为无效点,本次起点设置无效
if not find:
self.start_point = False
self.end_point = True
self.x1, self.y1 = 0, 0
info = "道路选点->鼠标右键按下,未选中已有路口\n选中坐标: ({:<3d}, {:>3d})".format(x, y)
self.interInfoEmit.emit(info)
# 当前起点已按下并确认,当前终点未按下
elif self.start_point and (not self.end_point):
self.x2, self.y2 = x, y
find = False
for i in range(len(self.nodes)):
condition1 = (abs(self.nodes[i][0] - self.x2) < 10)
condition2 = (abs(self.nodes[i][1] - self.y2) < 10)
condition3 = (self.nodes[i][0] != self.x1)
condition4 = (self.nodes[i][1] != self.y1)
if (not condition3) and (not condition4):
info = "道路选点->鼠标右键按下,取消起点\n起点坐标: ({:<3d}, {:>3d})".format(self.x1, self.y1)
self.interInfoEmit.emit(info)
if condition1 and condition2 and condition3 and condition4:
find = True
# 确认终点
self.x2, self.y2 = self.nodes[i][0], self.nodes[i][1]
self.dest_node = i + 1
info = "道路选点->鼠标右键按下,选中终点\n终点坐标: ({:<3d}, {:>3d})".format(self.x2, self.y2)
self.interInfoEmit.emit(info)
reply = QMessageBox.question(self, '道路方向', '设置为双向道路', QMessageBox.Yes | QMessageBox.No,
QMessageBox.Yes)
if reply == QMessageBox.No:
# 添加单向道路
sn, dn = self.start_node, self.dest_node
road = [self.x1, self.y1, self.x2, self.y2, sn, dn]
map_roads.append(road)
info = "道路选点->鼠标右键按下,选中终点->单向道路\n起点坐标: ({:<3d}, {:>3d})\n终点坐标: ({:<3d}, {:>3d})". \
format(self.x1, self.y1, self.x2, self.y2)
self.interInfoEmit.emit(info)
info = "道路{:<2d} 起点:({:<3d},{:>3d}) → 终点:({:<3d},{:>3d})". \
format(len(self.road_info) + 1, self.x1, self.y1, self.x2, self.y2)
self.road_info.append(info)
self.roadInfoEmit.emit(self.road_info)
# 添加操作记录
self.operation_record.append([2, road])
elif reply == QMessageBox.Yes:
# 添加双向道路
new_line = self.solve_new_line(self.x1, self.y1, self.x2, self.y2, 5)
l1, l2 = new_line[0], new_line[1]
sn, dn = self.start_node, self.dest_node
road_1 = [int(l1[0]), int(l1[1]), int(l1[2]), int(l1[3]), sn, dn]
road_2 = [int(l2[0]), int(l2[1]), int(l2[2]), int(l2[3]), dn, sn]
map_roads.append(road_1)
map_roads.append(road_2)
info = "道路选点->鼠标右键按下,选中终点->双向道路\n起点坐标: ({:<3d}, {:>3d})\n终点坐标: ({:<3d}, {:>3d})". \
format(self.x1, self.y1, self.x2, self.y2)
self.interInfoEmit.emit(info)
info = "道路{:<2d} 起点:({:<3d},{:>3d}) → 终点:({:<3d},{:>3d})". \
format(len(self.road_info) + 1, int(l1[0]), int(l1[1]), int(l1[2]), int(l1[3]))
self.road_info.append(info)
info = "道路{:<2d} 起点:({:<3d},{:>3d}) → 终点:({:<3d},{:>3d})". \
format(len(self.road_info) + 1, int(l2[0]), int(l2[1]), int(l2[2]), int(l2[3]))
self.road_info.append(info)
self.roadInfoEmit.emit(self.road_info)
# 添加操作记录
self.operation_record.append([3, road_1, road_2])
# 设置一下次起点未按下,终点已按下并确认
self.start_point = False
self.end_point = True
# 立即更新绘图
self.update()
break
# 若选中的为无效点,本次终点设置无效,起点无效,道路无效
if not find:
self.start_point = False
self.end_point = True
self.x2, self.y2 = 0, 0
self.x1, self.y1 = 0, 0
else:
info = "道路选点->鼠标右键按下,无效操作\n少于两个路口,无法连接道路\n选中坐标: ({:<3d}, {:>3d})".format(x, y)
self.interInfoEmit.emit(info)
# 实时路况绘制
def realtime_condition_paint(self):
painter = QPainter(self)
# 显示道路
for i in range(len(self.roads)):
line = QLine(self.roads[i][-4], self.roads[i][-3], self.roads[i][-2], self.roads[i][-1])
try:
score = road_crowd_data[i]
except (IndexError, Exception):
score = 0
color = self.crowded_level[score]
r, g, b = color[0], color[1], color[2]
painter.setPen(QPen(QColor(r, g, b), self.line_width, Qt.SolidLine))
painter.drawLine(line)
# painter.setPen(QPen(Qt.black, self.line_width, Qt.SolidLine))
# m = (self.roads[i][-4] + self.roads[i][-2]) // 2
# n = (self.roads[i][-3] + self.roads[i][-1]) // 2
# painter.drawText(m, n, str(i + 1))
# 显示道路结点
cross_num = 1
for i in range(len(self.nodes)):
# 交叉口点位
if self.nodes[i][2]:
rect = QRect(self.nodes[i][-2] - 4, self.nodes[i][-1] - 4, 8, 8)
painter.setPen(QPen(Qt.black, self.line_width, Qt.SolidLine))
painter.fillRect(rect, Qt.blue)
painter.drawText(self.nodes[i][-2] - 8, self.nodes[i][-1] - 8, str(cross_num))
cross_num += 1
# 道路选点绘制
def choose_point_paint(self):
painter = QPainter(self)
# 画出已存在的道路
for i in range(len(self.roads)):
coordinate = self.roads[i]
line = QLine(coordinate[0], coordinate[1], coordinate[2], coordinate[3])
painter.setPen(QPen(Qt.red, self.line_width, Qt.SolidLine))
painter.drawLine(line)
# 画出已存在的点
if len(self.nodes) != 0:
cross_num = 1
for i in range(len(self.nodes)):
condition1 = self.x1 != 0 and self.y1 != 0
condition2 = self.x2 == 0 and self.y2 == 0
condition3 = (self.nodes[i][0] == self.x1) and (self.nodes[i][1] == self.y1)
# 刚选中一条新的道路起点,着重突出该点
if condition1 and condition2 and condition3:
rect = QRect(self.x1 - 6, self.y1 - 6, 12, 12)
painter.setPen(QPen(Qt.white, self.line_width, Qt.SolidLine))
painter.fillRect(rect, Qt.white)
# 其他点原样画出
else:
rect = QRect(self.nodes[i][0] - 4, self.nodes[i][1] - 4, 8, 8)
painter.setPen(QPen(Qt.black, self.line_width, Qt.SolidLine))
# 交叉口点位
if self.nodes[i][2]:
painter.fillRect(rect, Qt.blue)
painter.drawText(self.nodes[i][0] - 8, self.nodes[i][1] - 8, str(cross_num))
cross_num += 1
# 普通点位
else:
painter.fillRect(rect, Qt.black)
# 鼠标点击事件
def mousePressEvent(self, event):
QLabel.mousePressEvent(self, event)
# 选点模式下鼠标点击事件
if map_mode == "choose_point":
# 鼠标左键按下
if event.buttons() == Qt.LeftButton:
self.left_mouse(event)
# 鼠标右键按下
elif event.buttons() == Qt.RightButton:
self.right_mouse(event)
# 电子地图界面绘制事件
def paintEvent(self, event):
super().paintEvent(event)
# 显示地图界面
if map_show:
global map_nodes, map_roads
# 设置定时刷新
if not self.update_timer:
self.update_timer = True
timer = QTimer(self)
timer.start(1000)
timer.timeout.connect(self.update)
self.nodes = map_nodes
self.roads = map_roads
# 地图模式为实时路况
if map_mode == "realtime_condition":
self.realtime_condition_paint()
# 地图模式为道路选点
elif map_mode == "choose_point":
self.choose_point_paint()
# 重写QLabel类,作为信号灯界面地图画布
class MyLabelLight(QLabel):
location_x, location_y = 0, 0
nodes = []
# 信号配时界面绘制事件
def paintEvent(self, event):
super().paintEvent(event)
self.nodes = map_nodes
painter = QPainter(self)
# 显示道路结点
cross_num = 1
for i in range(len(self.nodes)):
# 交叉口点位
if self.nodes[i][2]:
rect = QRect(self.nodes[i][-2] - 4, self.nodes[i][-1] - 4, 8, 8)
painter.fillRect(rect, Qt.blue)
painter.setPen(QPen(Qt.black, 2, Qt.SolidLine))
painter.drawText(self.nodes[i][-2] - 8, self.nodes[i][-1] - 8, str(cross_num))
cross_num += 1
# 显示定位点
if self.location_x != 0 and self.location_y != 0:
painter.drawPixmap(self.location_x - 15, self.location_y - 30, QPixmap("resource/icon/location.png"))
# 主窗口界面
class MainWindow(QMainWindow, ui):
def __init__(self):
QMainWindow.__init__(self)
self.setupUi(self)
self.resize(1280, 690)
self.setWindowTitle("城市道路智慧交通管理系统")
self.setWindowIcon(QIcon("resource/icon/icon.png"))
self.setFixedSize(self.width(), self.height())
self.setup_map_ui = set_map.Setup_Map()
self.setup_sql_ui = set_mysql.Setup_Sql()
self.versionDialog = aboutDialog.versionDialog()
self.contactDialog = contact.contactDialog()
self.DB = DataBase.DataBase(mysql_info)
self.timer_map = QTimer(self)
self.timer_light = QTimer(self)
self.timer_video = QTimer(self)
self.map_label = MyLabel(self.label_map)
self.map_light_label = MyLabelLight(self.label_map_light)
self.undo_operation_record = []
self.qss_style = []
self.count_down_time = [10, 10, 10]
self.pre_count_down_time = [10, 10, 10]
self.cap = cv.VideoCapture("./resource/video/demo.mp4")
self.map_bg = "./resource/map/BG.png"
# 主界面界面切换槽函数
self.pushButton1.clicked.connect(self.switch_to_map_panel)
self.pushButton2.clicked.connect(self.switch_to_light_time_panel)
self.pushButton3.clicked.connect(self.switch_to_traffic_state_panel)
self.pushButton4.clicked.connect(self.switch_to_work_state_panel)
# 菜单栏触发信号
self.action_import.triggered.connect(self.import_data)
self.action_export.triggered.connect(self.export_data)
self.action_setup_map.triggered.connect(self.setup_map_ui.show)
self.action_setup_sql.triggered.connect(self.setup_sql_ui.show)
self.action_local.triggered.connect(self.open_local_help_chm)
self.action_online.triggered.connect(self.open_online_help_network)
self.action_version.triggered.connect(self.versionDialog.show)
self.action_contact.triggered.connect(self.contactDialog.show)
# 自定义信号槽函数连接
self.setup_map_ui.mapInfoEmit.connect(self.set_map_info)
self.setup_sql_ui.sqlInfoEmit.connect(self.set_sql_info)
self.map_label.interInfoEmit.connect(self.show_inter_info)
self.map_label.roadInfoEmit.connect(self.show_road_info)
# 隐藏tab标签
self.tabWidget.tabBar().setVisible(False)
# 初始化主界面
self.init_map()
self.init_light()
self.init_status()
# 默认显示电子地图界面
self.switch_to_map_panel()
# 切换到电子地图界面
def switch_to_map_panel(self):
global map_show
self.tabWidget.setCurrentIndex(0)
self.statusBar().showMessage("")
map_show = True
self.timer_map.start(1000)
# 切换到信号灯配时界面
def switch_to_light_time_panel(self):
global map_show
self.tabWidget.setCurrentIndex(1)
self.statusBar().showMessage("")
map_show = False
self.timer_map.stop()
# 切换到交通状态界面·
def switch_to_traffic_state_panel(self):
global map_show
self.tabWidget.setCurrentIndex(2)
self.statusBar().showMessage("")
map_show = False
self.timer_map.stop()
# 切换到工作状态界面
def switch_to_work_state_panel(self):
global map_show
self.tabWidget.setCurrentIndex(3)
self.statusBar().showMessage("")
map_show = False
self.timer_map.stop()
# 初始化地图界面
def init_map(self):
# 设置控件区域鼠标的光标形状(默认为箭头)
self.map_label.setCursor(Qt.ArrowCursor)
# 设置按钮可用状态
self.pushButton_choose.setText("道路选点")
self.pushButton_choose.setEnabled(True)
self.pushButton_clear_all.setEnabled(False)
self.pushButton_do.setEnabled(False)
self.pushButton_undo.setEnabled(False)
# 设置按钮图标
self.pushButton_choose.setIcon(QIcon(QPixmap("./resource/icon/switch.png")))
self.pushButton_clear_all.setIcon(QIcon(QPixmap("./resource/icon/clear.png")))
self.pushButton_do.setIcon(QIcon(QPixmap("./resource/icon/do.png")))
self.pushButton_undo.setIcon(QIcon(QPixmap("./resource/icon/undo.png")))
self.pushButton_play.setIcon(QIcon(QPixmap("./resource/icon/play.png")))
# 让图片自适应label大小
self.map_label.setScaledContents(True)
# 显示交互提示信息
self.textBrowser_inter.clear()
self.textBrowser_inter.append("实时路况模式:")
# 槽函数连接
self.timer_map.timeout.connect(self.show_road_condition)
self.pushButton_play.clicked.connect(self.play_video)
self.timer_video.timeout.connect(self.show_pic)
self.pushButton_choose.clicked.connect(self.switch_map_mode)
self.pushButton_clear_all.clicked.connect(self.clear_all_choose)
self.pushButton_do.clicked.connect(self.do_operation)
self.pushButton_undo.clicked.connect(self.undo_operation)
# 设置地图背景图片
self.map_label.resize(648, 543)
self.map_light_label.resize(648, 543)
self.map_label.setPixmap(QPixmap(self.map_bg))
self.map_light_label.setPixmap(QPixmap(self.map_bg))
self.map_mode()
self.show_road_condition()
# 播放视频设置
def play_video(self):
if self.pushButton_play.text() == "播放":
self.pushButton_play.setText("关闭")
self.pushButton_play.setIcon(QIcon(QPixmap("./resource/icon/shutdown.png")))
self.fps_count = 0
# 文件路径
self.cap = cv.VideoCapture("./resource/video/demo.mp4")
# 网络摄像头地址
# self.cap = cv.VideoCapture("rtsp://account:password@192.168.0.35:554/11")
# 笔记本电脑自带摄像头或台式机电脑外置USB摄像头
# self.cap = cv.VideoCapture(0)
self.timer_video.start(int(1000 / self.cap.get(cv.CAP_PROP_FPS)))
else:
self.pushButton_play.setText("播放")
self.pushButton_play.setIcon(QIcon(QPixmap("./resource/icon/play.png")))
self.timer_video.stop()
self.label_video.setText("路口网络摄像头实时画面")
# 显示视频
def show_pic(self):
success, frame = self.cap.read()
if success:
self.fps_count += 1
frame = cv.resize(frame, (480, 320))
# cv.imwrite("./resource/image/" + str(self.fps_count) + ".jpg", frame)
show = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
show_image = QImage(show.data, show.shape[1], show.shape[0], QImage.Format_RGB888)
self.label_video.setPixmap(QPixmap.fromImage(show_image))
# 导入数据
def import_data(self):
global map_nodes, map_roads
self.textBrowser_inter.clear()
self.textBrowser_inter.append("导入数据!")
reply = QFileDialog.getOpenFileName(self, '导入文件', './resource/data/data.txt', "文本(*.txt)")
try:
if reply[0]:
# 从文件中读取数据
with open(reply[0], "r", encoding="utf-8") as f:
lines = f.readlines()
nodes = []
roads = []
cnt = 0
for i in range(len(lines)):
line = lines[i].split()
if line[0] == "id":
cnt += 1
else:
if cnt == 1:
nodes.append(list(map(int, line)))
elif cnt == 2:
roads.append(list(map(int, line)))
if nodes and roads:
map_nodes = nodes
map_roads = roads
QMessageBox.about(self, '提示', '导入数据成功')
self.textBrowser_inter.clear()
self.textBrowser_inter.append("导入数据成功,导入文件为{}".format(reply[0]))
else:
QMessageBox.about(self, '提示', '导入数据失败,因为文件内容不符合规范')
self.textBrowser_inter.clear()
self.textBrowser_inter.append("导入数据失败,选择的导入文件为{}".format(reply[0]))
else:
QMessageBox.about(self, '提示', '导入数据失败,因为你未选中一个有效的文件')
self.textBrowser_inter.clear()
self.textBrowser_inter.append("数据导入失败!")
except (IndexError, Exception):
pass
# 导出选点数据
def export_data(self):
global map_nodes, map_roads
if map_mode == "choose_point":
if map_roads or map_nodes:
reply = QFileDialog.getSaveFileName(self, '保存文件', './resource/data/data.txt', "文本(*.txt)")
try:
if reply[0]:
content = ""
# 开始保存nodes
lines = "id" + "\t\t" + "is" + "\t\t" + "ar" + "\t\t" + "cr" + "\t\t" + \
"ph" + "\t\t" + "x" + "\t\t" + "y" + "\n"
content += lines
for row, line in enumerate(map_nodes):
lines = str(row + 1) + "\t\t" + str(line[2]) + "\t\t" + str(line[3]) + "\t\t" + \
str(line[4]) + "\t\t" + str(line[5]) + "\t\t" + str(line[0]) + "\t\t" + \
str(line[1]) + "\n"
content += lines
# 开始保存roads
lines = "id" + "\t\t" + "sn" + "\t\t" + "dn" + "\t\t" + "sx" + "\t\t" + \
"sy" + "\t\t" + "dx" + "\t\t" + "dy" + "\n"
content += lines
for row, line in enumerate(map_roads):
lines = str(row + 1) + "\t\t" + "\t\t" + str(line[4]) + "\t\t" + \
str(line[5]) + "\t\t" + str(line[0]) + "\t\t" + str(line[1]) + "\t\t" + \
str(line[2]) + "\t\t" + str(line[3]) + "\n"
content += lines
if content:
with open(reply[0], "a", encoding="utf-8") as f:
f.writelines(content)
QMessageBox.information(self, "提示", "导出成功")
self.textBrowser_inter.clear()
self.textBrowser_inter.append("数据导出成功,保存文件为:{}".format(reply[0]))
else:
QMessageBox.information(self, "提示", "导出失败")
self.textBrowser_inter.clear()
self.textBrowser_inter.append("数据导出失败!")
except (IndexError, Exception):
pass
else:
QMessageBox.about(self, '提示', '暂无数据可以导出,请先进行选点操作')
self.textBrowser_inter.clear()
self.textBrowser_inter.append("数据导出失败!")
else:
QMessageBox.about(self, '提示', '请先切换至选点模式')
# 打开本地帮助文档
def open_local_help_chm(self):
path = os.getcwd() + r"/resource/help/help.CHM"
if os.path.exists(path):
# 运行为windows平台
if sys.platform == 'win32':
os.startfile(path)
# 运行为linux平台
else:
if 'XDG_CURRENT_DESKTOP' in os.environ:
opener = ['xdg-open']
elif 'EDITOR' in os.environ:
opener = [os.environ['EDITOR']]
else:
opener = ['vi']
opener.append(path)
subprocess.call(opener)
self.textBrowser_inter.clear()
info = "打开本地帮助CHM文档,文档地址为{}".format(path)
self.textBrowser_inter.append(info)
else:
QMessageBox.warning(self, "提示", "当前目录下帮助文档不存在")
self.textBrowser_inter.clear()
info = "本地帮助CHM文档不存在,请将帮助文档复制到当前目录下的{}".format(path)
self.textBrowser_inter.append(info)
# 网络在线帮助
@staticmethod
def open_online_help_network():
webbrowser.open("https://www.baidu.com/")
# 显示界面交互信息
def show_inter_info(self, info):
self.textBrowser_inter.clear()
self.textBrowser_inter.append(info)
# 显示道路信息
def show_road_info(self, info):
self.textBrowser_road.clear()
for row, line in enumerate(info):
self.textBrowser_road.append(line)
# 配置地图信息完成
def set_map_info(self, info):
self.map_label.line_width = info[0]
self.map_label.crowded_level = info[1]
# 配置数据库信息完成
def set_sql_info(self, info):
if use_database:
self.DB.connect_mysql(info)
self.get_road_data()
# 撤销操作
def undo_operation(self):
if self.map_label.operation_record:
last_operation = self.map_label.operation_record.pop()
self.undo_operation_record.append(last_operation)
# 撤销交叉口选点
if last_operation[0] == 0:
map_nodes.pop()
self.textBrowser_inter.clear()
self.textBrowser_inter.append("撤销最近的一个交叉口选点操作!")
# 撤销道路起点选择
elif last_operation[0] == 1:
self.map_label.x1, self.map_label.y1 = 0, 0
self.map_label.start_point = False
self.map_label.end_point = True
self.textBrowser_inter.clear()
self.textBrowser_inter.append("撤销最近的一条道路起点选择操作!")
# 撤销单向道路连接
elif last_operation[0] == 2:
map_roads.pop()
# 取消终点
self.map_label.x2, self.map_label.y2 = 0, 0
# 调出最近的起点选择操作
for row, line in enumerate(self.map_label.operation_record[::-1]):
# 存在起点
if len(line[1]) == 2:
self.map_label.x1, self.map_label.y1 = line[1][0], line[1][1]
self.map_label.start_point = True
self.map_label.end_point = False
break
self.textBrowser_inter.clear()
self.textBrowser_inter.append("撤销最近的一次单向道路连接操作!")
# 撤销双向道路连接
elif last_operation[0] == 3:
map_roads.pop()
map_roads.pop()
# 取消终点
self.map_label.x2, self.map_label.y2 = 0, 0
# 调出最近的起点选择操作
for row, line in enumerate(self.map_label.operation_record[::-1]):
# 存在起点
if len(line[1]) == 2:
self.map_label.x1, self.map_label.y1 = line[1][0], line[1][1]
self.map_label.start_point = True
self.map_label.end_point = False
break
self.textBrowser_inter.clear()
self.textBrowser_inter.append("撤销最近的一次双向道路连接操作!")
else:
QMessageBox.warning(self, "警告", "现在没有记录可以撤销")
# 恢复操作
def do_operation(self):
if self.undo_operation_record:
last_undo_operation = self.undo_operation_record.pop()
self.map_label.operation_record.append(last_undo_operation)
# 恢复交叉口选点
if last_undo_operation[0] == 0:
map_nodes.append(last_undo_operation[1])
self.textBrowser_inter.clear()
self.textBrowser_inter.append("恢复最近的一个交叉口选点操作!")
# 恢复道路起点选择
elif last_undo_operation[0] == 1:
self.map_label.x1 = last_undo_operation[1][0]
self.map_label.y1 = last_undo_operation[1][1]
self.map_label.start_point = True
self.map_label.end_point = False
self.textBrowser_inter.clear()
self.textBrowser_inter.append("恢复最近的一条道路起点选择操作!")
# 恢复单向道路连接
elif last_undo_operation[0] == 2:
self.map_label.x1 = 0
self.map_label.y1 = 0
self.map_label.start_point = False
self.map_label.end_point = True
map_roads.append(last_undo_operation[1])
self.textBrowser_inter.clear()
self.textBrowser_inter.append("恢复最近的一次单向道路连接操作!")
# 恢复双向道路连接
elif last_undo_operation[0] == 3:
self.map_label.x1 = 0
self.map_label.y1 = 0
self.map_label.start_point = False
self.map_label.end_point = True
map_roads.append(last_undo_operation[1])
map_roads.append(last_undo_operation[2])
self.textBrowser_inter.clear()
self.textBrowser_inter.append("恢复最近的一次双向道路连接操作!")
else:
QMessageBox.warning(self, "警告", "现在没有记录可以恢复")
# 清除所有选点
def clear_all_choose(self):
reply = QMessageBox.warning(self, '警告', '即将清除当前全部选点数据,是否继续清除',
QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
if reply == QMessageBox.Yes:
global map_nodes, map_roads
map_nodes = []
map_roads = []
self.map_label.road_info = []
self.map_label.operation_record = []
self.undo_operation_record = []
self.textBrowser_inter.clear()
self.textBrowser_road.clear()
self.textBrowser_inter.append("清除所有选点数据")
# 切换地图模式
def switch_map_mode(self):
global map_mode
if map_mode == "realtime_condition":
map_mode = "choose_point"
self.textBrowser_inter.clear()
self.textBrowser_inter.append("道路选点模式:\n鼠标左键选择路口\n鼠标右键依次选择道路起点、终点")
self.textBrowser_road.clear()
self.map_mode()
else:
reply = QMessageBox.warning(self, '警告', '即将丢失当前选点数据,请确保已经导出正确的数据,是否继续退出',
QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
if reply == QMessageBox.Yes:
map_mode = "realtime_condition"
self.map_label.road_info = []
self.textBrowser_inter.clear()
self.textBrowser_inter.append("实时路况模式:")
self.textBrowser_road.clear()
self.map_mode()
# 设置地图模式
def map_mode(self):
if map_mode == "realtime_condition":
# 设置控件区域鼠标的光标形状为箭头
self.map_label.setCursor(Qt.ArrowCursor)
# 清空道路信息框
self.textBrowser_road.clear()
# 设置实时路况模式下按钮状态
self.pushButton_choose.setText("道路选点")
self.pushButton_choose.setEnabled(True)
self.pushButton_clear_all.setEnabled(False)
self.pushButton_do.setEnabled(False)
self.pushButton_undo.setEnabled(False)
# 读取数据
self.get_road_data()
else:
global map_nodes, map_roads
# 清空数据
map_nodes = []
map_roads = []
# 设置控件区域鼠标的光标形状为十字形
self.map_label.setCursor(Qt.CrossCursor)
# 设置道路选点模式下按钮状态
self.pushButton_choose.setText("实时路况")
self.pushButton_choose.setEnabled(True)
self.pushButton_clear_all.setEnabled(True)
self.pushButton_do.setEnabled(True)
self.pushButton_undo.setEnabled(True)
# 获取道路数据
def get_road_data(self):
global map_nodes, map_roads, map_threshold, area_cross, area_cross_phase, area_cross_road
# 清空数据
map_nodes = []
map_roads = []
map_threshold = []
if use_database:
# 从数据库获取数据
map_nodes = self.DB.query_map_nodes()
map_roads = self.DB.query_map_roads()
map_threshold = self.DB.query_map_threshold()
if (not map_nodes) or (not map_roads):
# 数据库数据不存在,自动从文件获取数据
data = self.read_file_data()
map_nodes, map_roads, map_threshold = data[0], data[1], data[2]
else:
# 从文件获取数据
data = self.read_file_data()
map_nodes, map_roads, map_threshold = data[0], data[1], data[2]
# 建立字典保存区域、道路、相位、路段之间的关系
area = []
area_cross = {}
area_cross_phase = {}
area_cross_road = {}
for row, line in enumerate(map_nodes):
node = line[1]
area_number = line[2]
cross_number = line[3]
max_phase = line[4]
if node:
if area_number not in area:
area.append(area_number)
area_cross[area_number] = [cross_number]
area_cross_phase[area_number] = [(cross_number, max_phase)]
else:
area_cross[area_number].append(cross_number)
area_cross_phase[area_number].append((cross_number, max_phase))
for row, line in enumerate(map_roads):
road_id = line[0]
area_number = line[1]
cross_number = line[2]
if area_number not in area_cross_road.keys():
area_cross_road[area_number] = [(cross_number, [road_id])]
else:
for i, e in enumerate(area_cross_road[area_number]):
if cross_number == e[0]:
area_cross_road[area_number][i][1].append(road_id)
break
else:
area_cross_road[area_number].append((cross_number, [road_id]))
# 读取文件数据
def read_file_data(self):
data_path = "./resource/data/data.xlsx"
try:
nodes = pd.read_excel(data_path, sheet_name=0, header=1).values
roads = pd.read_excel(data_path, sheet_name=1, header=1).values
threshold = pd.read_excel(data_path, sheet_name=2, header=1).values
self.textBrowser_inter.clear()
self.textBrowser_inter.append("程序从文件中加载数据,文件地址为{}".format(data_path))
return [nodes, roads, threshold]
except (IndexError, Exception):
self.textBrowser_inter.clear()
self.textBrowser_inter.append("程序从文件中加载数据失败,文件地址为{}".format(data_path))
return [[], [], []]
# 车流量转换为拥堵等级
@staticmethod
def flow_convert_crowd(flow):
crowd = []
for i in range(len(flow)):
crowd.append(0)
for i in range(len(flow)):
for row, line in enumerate(map_threshold):
if line[1] == flow[i][0]:
g1, g2, g3 = line[-3], line[-2], line[-1]
if flow[i][1] < g1:
crowd[i] = 0
elif g1 <= flow[i][1] < g2:
crowd[i] = 1
elif g2 <= flow[i][1] < g3:
crowd[i] = 2
else:
crowd[i] = 3
break
return crowd
# 显示道路状况
def show_road_condition(self):
global road_crowd_data, road_flow_data, map_roads, use_database
if map_mode == "realtime_condition":
if use_database:
# 利用数据库查询道路拥堵程度得分
info = ["20210227", "08:00:00", 0, 0, 0]
road_flow_data = self.DB.query_roads_flow(info)
road_crowd_data = self.flow_convert_crowd(road_flow_data)
else:
# 利用随机数生成拥堵程度分级得分
road_flow_data = []
for i in range(len(map_roads)):
road_flow_data.append([i + 1, random.randint(30, 300)])
road_crowd_data = self.flow_convert_crowd(road_flow_data)
# 数据不存在
if not road_crowd_data:
self.textBrowser_road.clear()
self.textBrowser_road.append("数据库查询道路拥堵程度失败")
else:
# 显示当前拥堵程度分数
self.textBrowser_road.clear()
for i in range(len(road_crowd_data)):
self.textBrowser_road.append("道路: {:>02d} -> 预测车流量: {:<3d} -> 拥堵等级: {:<1d}".
format(i + 1, road_flow_data[i][1], road_crowd_data[i]))
self.textBrowser_road.moveCursor(QTextCursor.Start)
# 初始化信号配时界面
def init_light(self):
# 三色信号灯样式表
self.qss_style = [
# 红灯
"""
QTextEdit{
border:none;
color:black;
font-size:11;
border-radius:50px;
padding-left:10px;
padding-right:10px;
text-align:middle;
background:LightGray;
background-color: rgb(255, 0, 0);
}
""",
# 绿灯
"""
QTextEdit{
border:none;
color:black;
font-size:11;
border-radius:50px;
padding-left:10px;
padding-right:10px;
text-align:middle;
background:LightGray;
background-color: rgb(0, 255, 0);
}
""",
# 黄灯
"""
QTextEdit{
border:none;
color:black;
font-size:11;
border-radius:50px;
padding-left:10px;
padding-right:10px;
text-align:middle;
background:LightGray;
background-color: rgb(255, 255, 0);
}
""",
# 熄灭
"""
QTextEdit{
border:none;
color:black;
font-size:11;
border-radius:50px;
padding-left:10px;
padding-right:10px;
text-align:middle;
background:LightGray;
background-color: rgb(190, 190, 190);
}
""",
]
# 让图片自适应label大小
self.map_light_label.setScaledContents(True)
# 设置lcd样式
self.lcdNumber.setStyleSheet("background-color: black")
self.lcdNumber.setSegmentStyle(QLCDNumber.Flat)
# 设置下拉框选项
self.load_area_cross_phase_combobox(1, self.comboBox2_1, self.comboBox2_2, self.comboBox2_3, 1, 0, 0)
# 启动定时器
self.timer_light.start(1000)
# 获取当前倒计时
self.get_count_time()
# 槽函数连接
self.timer_light.timeout.connect(self.show_light_time)
self.comboBox2_1.currentIndexChanged.connect(self.select_area_combobox)
self.comboBox2_2.currentIndexChanged.connect(self.select_cross_combobox)
self.comboBox2_3.currentIndexChanged.connect(self.get_count_time)
# 选中区域下拉框
def select_area_combobox(self):
page = self.tabWidget.currentIndex()
if page == 1:
self.load_cross_combobox(page, self.comboBox2_1, self.comboBox2_2)
self.get_count_time()
elif page == 2:
self.load_cross_combobox(page, self.comboBox3_3, self.comboBox3_4)
elif page == 3:
self.load_cross_combobox(page, self.comboBox4_3, self.comboBox4_4)
# 选中路口下拉框
def select_cross_combobox(self):
page = self.tabWidget.currentIndex()
if page == 1:
self.load_phase_combobox(page, self.comboBox2_1, self.comboBox2_2, self.comboBox2_3)
self.get_count_time()
elif page == 2:
self.load_phase_combobox(page, self.comboBox3_3, self.comboBox3_4, self.comboBox3_5)
elif page == 3:
self.load_phase_combobox(page, self.comboBox4_3, self.comboBox4_4, self.comboBox4_5)
# 加载路口下拉框选项
def load_cross_combobox(self, page, box1, box2):
global map_nodes
box2.currentIndexChanged.disconnect(self.select_cross_combobox)
if page == 1:
area_number = int(box1.currentText()[2::])
box2.clear()
for row, line in enumerate(area_cross[area_number]):
box2.addItem("路口" + str(line))
box2.currentIndexChanged.connect(self.select_cross_combobox)
box2.setCurrentIndex(0)
self.select_cross_combobox()
elif page == 2 or page == 3:
area_index = int(box1.currentIndex())
cross_index = int(box2.currentIndex())
area_text = box1.currentText()
cross_text = box2.currentText()
# 区域编号不为0,即区域未变为"全部"
if area_index != 0:
area_number = int(area_text[2::])
box2.clear()
box2.addItem("全部")
all_cross_number = []
for row, line in enumerate(area_cross[area_number]):
all_cross_number.append(line)
box2.addItem("路口" + str(line))
box2.currentIndexChanged.connect(self.select_cross_combobox)
# 原路口编号不为0,即原路口未选中"全部"
if cross_index != 0:
cross_number = int(cross_text[2::])
for i in range(len(all_cross_number)):
if all_cross_number[i] == cross_number:
box2.setCurrentIndex(i + 1)
break
else:
box2.setCurrentIndex(0)
else:
box2.setCurrentIndex(0)
self.select_cross_combobox()
# 区域编号为0,即区域变为"全部"
else:
box2.clear()
box2.addItem("全部")
all_cross_number = []
for value in area_cross.values():
for i, element in enumerate(value):
if element not in all_cross_number:
all_cross_number.append(element)
box2.addItem("路口" + str(element))
box2.currentIndexChanged.connect(self.select_cross_combobox)
# 原路口编号不为0,即原路口未选中"全部"
if cross_index != 0:
cross_number = int(cross_text[2::])
if cross_number in all_cross_number:
for i in range(len(all_cross_number) + 1):
if box2.itemText(i) == "路口" + str(cross_number):
box2.setCurrentIndex(i)
break
else:
box2.setCurrentIndex(0)
else:
box2.setCurrentIndex(0)
self.select_cross_combobox()
# 加载相位下拉框选项
def load_phase_combobox(self, page, box1, box2, box3):
if page == 1:
box3.currentIndexChanged.disconnect(self.get_count_time)
area_number = int(box1.currentText()[2::])
cross_number = int(box2.currentText()[2::])
phase_index = int(box3.currentIndex())
box3.clear()
for row, line in enumerate(area_cross_phase[area_number]):
if line[0] == cross_number:
phase_amount = line[1]
for i in range(phase_amount):
box3.addItem("相位" + str(i + 1))
if phase_amount > phase_index >= 0:
box3.setCurrentIndex(phase_index)
else:
box3.setCurrentIndex(0)
break
box3.currentIndexChanged.connect(self.get_count_time)
# 相位变为路段
elif page == 2 or page == 3:
area_index = int(box1.currentIndex())
cross_index = int(box2.currentIndex())
area_text = box1.currentText()
cross_text = box2.currentText()
# 区域、路口编号均不为0,即区域、路口未变为"全部"
if area_index != 0 and cross_index != 0:
area_number = int(area_text[2::])
cross_number = int(cross_text[2::])
box3.clear()
box3.addItem("全部")
all_road_number = []
for row, line in enumerate(area_cross_road[area_number]):
if line[0] == cross_number:
for i in range(len(line[1])):
all_road_number.append(line[1][i])
all_road_number.sort()
for i in range(len(all_road_number)):
box3.addItem("路段" + str(all_road_number[i]))
box3.setCurrentIndex(0)
# 区域编号为0,即区域变为"全部", 路口编号不为0,即路口不变为"全部"
elif area_index == 0 and cross_index != 0:
cross_number = int(cross_text[2::])
box3.clear()
box3.addItem("全部")
all_road_number = []
for value in area_cross_road.values():
for i, element in enumerate(value):
if element[0] == cross_number:
for j in range(len(element[1])):
all_road_number.append(element[1][j])
all_road_number.sort()
for i in range(len(all_road_number)):
box3.addItem("路段" + str(all_road_number[i]))
box3.setCurrentIndex(0)
# 区域编号不为0,即区域不变为"全部", 路口编号为0,即路口变为"全部"
elif area_index != 0 and cross_index == 0:
area_number = int(area_text[2::])
box3.clear()
box3.addItem("全部")
all_road_number = []
for row, line in enumerate(area_cross_road[area_number]):
for i in range(len(line[1])):
all_road_number.append(line[1][i])
all_road_number.sort()
for i in range(len(all_road_number)):
box3.addItem("路段" + str(all_road_number[i]))
box3.setCurrentIndex(0)
# 区域编号为0,即区域变为"全部", 路口编号为0,即路口变为"全部"
elif area_index == 0 and cross_index == 0:
box3.clear()
box3.addItem("全部")
for i in range(len(map_roads)):
box3.addItem("路段" + str(i + 1))
box3.setCurrentIndex(0)
# 加载区域、路口、路段下拉框选项
@staticmethod
def load_area_cross_phase_combobox(page, box1, box2, box3, idx1, idx2, idx3):
global area_cross, area_cross_phase, area_cross_road, map_nodes, map_roads
box1.clear()
box2.clear()
box3.clear()
if page == 1:
for key in area_cross.keys():
box1.addItem("区域" + str(key))
box1.setCurrentIndex(idx1)
area_number = int(box1.currentText()[2::])
for row, line in enumerate(area_cross[area_number]):
box2.addItem("路口" + str(line))
box2.setCurrentIndex(idx2)
cross_number = int(box2.currentText()[2::])
for row, line in enumerate(area_cross_phase[area_number]):
if line[0] == cross_number:
for i in range(line[1]):
box3.addItem("相位" + str(i + 1))
box3.setCurrentIndex(idx3)
elif page == 2 or page == 3:
box1.addItem("全部")
box2.addItem("全部")
box3.addItem("全部")
for key in area_cross.keys():
box1.addItem("区域" + str(key))
box1.setCurrentIndex(idx1)
all_cross_number = []
for value in area_cross.values():
for i, element in enumerate(value):
if element not in all_cross_number:
all_cross_number.append(element)
box2.addItem("路口" + str(element))
box2.setCurrentIndex(idx2)
for i in range(len(map_roads)):
box3.addItem("路段" + str(i + 1))
box3.setCurrentIndex(idx3)
# 查询当前倒计时数据
def query_count_time_data(self):
# 汇总查询信息
area = self.comboBox2_1.currentText()[2::]
cross = self.comboBox2_2.currentText()[2::]
phase = self.comboBox2_3.currentIndex() + 1
# 存在相位,路口有信号灯
if phase > 0:
if use_database:
# 通过数据库获取当前倒计时
data = self.DB.query_count_down_time([area, cross, phase])
if data:
result = data[0]
else:
result = [0, 0, 0]
else:
# 随机生成当前倒计时
result = random.choices(range(2, 4), k=3)
# 不存在相位,路口未接入信号灯
else:
result = []
return result
# 获取最新倒计时并显示
def get_count_time(self):
# 显示定位图标
area_number = int(self.comboBox2_1.currentText()[2::])
cross_number = int(self.comboBox2_2.currentText()[2::])
for row, line in enumerate(map_nodes):
if line[1] and line[2] == area_number and line[3] == cross_number:
self.map_light_label.location_x = line[-2]
self.map_light_label.location_y = line[-1]
self.map_light_label.update()
# 查询当前倒计时数据
self.count_down_time = self.query_count_time_data()
# 判断并显示倒计时结果
if self.count_down_time:
r, g, y = self.count_down_time[0], self.count_down_time[1], self.count_down_time[2]
if (r != 0) and (g != 0) and (y != 0):
self.timer_light.start()
light_off = False
self.label_hint.setVisible(False)
self.label_count_down.setVisible(True)
self.label_count.setVisible(True)
# 显示当前倒计时
self.label_count_down.setText("红: {},绿: {},黄: {}".format(r, g, y))
# 立即显示信号灯时间
self.show_light_time()
else:
self.label_hint.setText("配时信息获取失败 显示异常")
light_off = True
else:
self.label_hint.setText("此路口红绿灯暂未接入系统")
light_off = True
if light_off:
self.timer_light.stop()
self.label_hint.setVisible(True)
self.label_hint.setStyleSheet("color: red")
self.label_count_down.setVisible(False)
self.label_count.setVisible(False)
# 显示熄灭状态
color = -1
# 加载信号灯
self.textEdit.setStyleSheet(self.qss_style[color])
# 设置显示内容
self.lcdNumber.display("%02d" % 0)
# 设置显示风格
self.lcdNumber.setSegmentStyle(QLCDNumber.Flat)
# 设置数字颜色
pat = self.lcdNumber.palette()
pat.setColor(QPalette.Normal, QPalette.WindowText, Qt.gray)
self.lcdNumber.setPalette(pat)
# 显示信号灯色及倒计时信息
def show_light_time(self):
# 黄灯倒计时为0,加载预测配时
if self.count_down_time[2] == 0:
# 获取下一周期的倒计时
self.count_down_time = self.query_count_time_data().copy()
# 显示最新倒计时信息
r, g, y = self.count_down_time[0], self.count_down_time[1], self.count_down_time[2]
self.label_count_down.setText("红: {},绿: {},黄: {}".format(r, g, y))
# 红色倒计时不为0,显示红灯
if self.count_down_time[0] != 0:
self.count_down_time[0] -= 1
self.textEdit.setStyleSheet(self.qss_style[0])
self.lcdNumber.display("%02d" % r)
pat = self.lcdNumber.palette()
pat.setColor(QPalette.Normal, QPalette.WindowText, Qt.red)
self.lcdNumber.setPalette(pat)
# 红色倒计时为0,绿色倒计时不为0,显示绿灯
elif self.count_down_time[1] != 0:
self.count_down_time[1] -= 1
self.textEdit.setStyleSheet(self.qss_style[1])
self.lcdNumber.display("%02d" % g)
pat = self.lcdNumber.palette()
pat.setColor(QPalette.Normal, QPalette.WindowText, Qt.green)
self.lcdNumber.setPalette(pat)
# 红色倒计时为0,绿色倒计时为0,黄色倒计时不为0,显示黄灯
elif self.count_down_time[2] != 0:
self.count_down_time[2] -= 1
self.textEdit.setStyleSheet(self.qss_style[2])
self.lcdNumber.display("%02d" % y)
pat = self.lcdNumber.palette()
pat.setColor(QPalette.Normal, QPalette.WindowText, Qt.yellow)
self.lcdNumber.setPalette(pat)
# 初始化状态界面
def init_status(self):
# 创建日期时间空间,并把当前日期时间赋值
self.dateEdit.setDisplayFormat('yyyy-MM-dd')
self.dateEdit_2.setDisplayFormat('yyyy-MM-dd')
# 设置为当前日期
self.dateEdit.setDate(QDate.currentDate())
self.dateEdit_2.setDate(QDate.currentDate())
# 设置日历控件允许弹出
self.dateEdit.setCalendarPopup(True)
self.dateEdit_2.setCalendarPopup(True)
# 设置表格内容不可编辑
self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.tableWidget_2.setEditTriggers(QAbstractItemView.NoEditTriggers)
# 设置表头样式
self.tableWidget.horizontalHeader().setStyleSheet(
"QHeaderView::section{background-color:rgb(155, 194, 230);font:10pt '宋体';color: black;};")
self.tableWidget_2.horizontalHeader().setStyleSheet(
"QHeaderView::section{background-color:rgb(155, 194, 230);font:10pt '宋体';color: black;};")
# 设置表格水平充满
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.tableWidget_2.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 设置下拉框选项
self.load_area_cross_phase_combobox(2, self.comboBox3_3, self.comboBox3_4, self.comboBox3_5, 0, 0, 0)
self.load_area_cross_phase_combobox(3, self.comboBox4_3, self.comboBox4_4, self.comboBox4_5, 0, 0, 0)
# 信息查询内容改变信号槽函数连接
self.comboBox3_3.currentIndexChanged.connect(self.select_area_combobox)
self.comboBox4_3.currentIndexChanged.connect(self.select_area_combobox)
self.comboBox3_4.currentIndexChanged.connect(self.select_cross_combobox)
self.comboBox4_4.currentIndexChanged.connect(self.select_cross_combobox)
# 查询功能
self.pushButton3_1.clicked.connect(self.show_traffic_state)
self.pushButton4_1.clicked.connect(self.show_work_state)
# 重置功能
self.pushButton3_2.clicked.connect(lambda: self.reset_status_query(0))
self.pushButton4_2.clicked.connect(lambda: self.reset_status_query(1))
# 按钮图标设置
self.pushButton3_1.setIcon(QIcon(QPixmap("./resource/icon/search.png")))
self.pushButton3_2.setIcon(QIcon(QPixmap("./resource/icon/reset.png")))
self.pushButton4_1.setIcon(QIcon(QPixmap("./resource/icon/search.png")))
self.pushButton4_2.setIcon(QIcon(QPixmap("./resource/icon/reset.png")))
# 重置状态界面查询
def reset_status_query(self, query):
if query == 0:
self.dateEdit.setDate(QDate.currentDate())
self.comboBox3_1.setCurrentIndex(8)
self.comboBox3_2.setCurrentIndex(0)
self.comboBox3_3.setCurrentIndex(0)
self.comboBox3_4.setCurrentIndex(0)
self.comboBox3_5.setCurrentIndex(0)
self.tableWidget.setRowCount(0)
self.tableWidget.clearContents()
else:
self.dateEdit_2.setDate(QDate.currentDate())
self.comboBox4_1.setCurrentIndex(8)
self.comboBox4_2.setCurrentIndex(0)
self.comboBox4_3.setCurrentIndex(0)
self.comboBox4_4.setCurrentIndex(0)
self.comboBox4_5.setCurrentIndex(0)
self.tableWidget_2.setRowCount(0)
self.tableWidget_2.clearContents()
# 汇总交通状态查询信息
@staticmethod
def collect_status_query_info(edit, box1, box2, box3, box4, box5):
date = edit.date().toString(Qt.ISODate)
date = date[:4] + date[5:7] + date[8:]
hour = box1.currentText()
minute = box2.currentText()
area = box3.currentIndex()
cross = box4.currentIndex()
road = box5.currentIndex()
if area != 0:
area = int(box3.currentText()[2::])
if cross != 0:
cross = int(box4.currentText()[2::])
if road != 0:
road = int(box5.currentText()[2::])
time = hour + ":" + minute + ":" + "00"
return [date, time, area, cross, road]
# 通过表格显示数据库状态查询结果
def show_status_result(self, query, info, table):
# 通过数据库查询结果
if query == 0:
data = self.DB.query_traffic_status(info)
else:
data = self.DB.query_work_status(info)
# 通过状态栏显示查询结果条数
self.statusBar().showMessage(" " * 5 + "查询完成 共查询到 {0} 条结果".format(len(data)))
# 通过表格显示查询结果
if data:
table.setRowCount(0)
table.insertRow(0)
row_position = 1
for row, line in enumerate(data):
for column, element in enumerate(line):
new_item = QTableWidgetItem(str(element))
if element != "异常":
new_item.setForeground(QBrush(QColor(0, 0, 0)))
else:
new_item.setForeground(QBrush(QColor(255, 0, 0)))
table.setItem(row, column, new_item)
table.item(row, column).setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
if row < len(data) - 1:
table.insertRow(row_position)
row_position += 1
# 交通状态界面:查询对应信息的数据new_item
def show_traffic_state(self):
# 清空查询结果表
self.tableWidget.clearContents()
# 获取查询条件
info = self.collect_status_query_info(self.dateEdit, self.comboBox3_1, self.comboBox3_2,
self.comboBox3_3, self.comboBox3_4, self.comboBox3_5)
# 显示数据库查询结果
self.show_status_result(0, info, self.tableWidget)
# 工作状态界面:查询对应信息的数据
def show_work_state(self):
# 清空查询结果表
self.tableWidget_2.clearContents()
# 获取查询条件
info = self.collect_status_query_info(self.dateEdit_2, self.comboBox4_1, self.comboBox4_2,
self.comboBox4_3, self.comboBox4_4, self.comboBox4_5)
# 显示数据库查询结果
self.show_status_result(1, info, self.tableWidget_2)
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化