添加 生成表达式 功能

main
zart 1 year ago
parent c22d011ee1
commit b3ae5007b2

@ -2,7 +2,9 @@
import math import math
import random import random
OPS = ['+', '-', '*', '/','^','sin','cos','tan'] OPS = ['+', '-', '*', '/', '^', 'sin', 'cos', 'tan']
def get_Aexps(nums=None): def get_Aexps(nums=None):
ops = OPS[:4] ops = OPS[:4]
if nums is None: if nums is None:
@ -30,6 +32,7 @@ def get_Aexps(nums=None):
else: else:
return "无法得出24点" return "无法得出24点"
def gen_exp(nums): # 生成表达式 def gen_exp(nums): # 生成表达式
ops = OPS[:4] ops = OPS[:4]
result = 0 result = 0
@ -47,6 +50,8 @@ def gen_exp(nums): # 生成表达式
continue # 跳过0除错误 continue # 跳过0除错误
if result != 24: if result != 24:
return "无法得出24点" return "无法得出24点"
def get_nums_group(nums): # 获取4个数的排列组合 def get_nums_group(nums): # 获取4个数的排列组合
group = [] group = []
for i in range(4): for i in range(4):
@ -69,8 +74,9 @@ class Node:
self.FaceColor = treeNode_value[6] self.FaceColor = treeNode_value[6]
def __str__(self): def __str__(self):
return f"NodeID: {self.NodeID}\t NodeType: {self.NodeType}\t Ops: {self.Ops}\t LeftNodeID: {self.LeftNodeID}\t RightNodeID: {self.RightNodeID}\t FaceValue: {self.FaceValue}\t FaceColor: {self.FaceColor}" return (
f"NodeID: {self.NodeID}\t NodeType: {self.NodeType}\t Ops: {self.Ops}\t LeftNodeID: {self.LeftNodeID}\t "
f"RightNodeID: {self.RightNodeID}\t FaceValue: {self.FaceValue}\t FaceColor: {self.FaceColor}")
def split_exp(expression): # 将表达式拆分为数字和运算符 def split_exp(expression): # 将表达式拆分为数字和运算符
@ -128,7 +134,7 @@ def get_postfix_expression_(expression): # 将中缀表达式转化为后缀表
return postfix return postfix
def get_postfix_expression(expression): def get_postfix_expression(expression): # 将中缀表达式转化为后缀表达式
# 多位数拆分 # 多位数拆分
expression = split_exp(expression) expression = split_exp(expression)
precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3, "sin": 4, "cos": 4, "tan": 4} precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3, "sin": 4, "cos": 4, "tan": 4}
@ -137,8 +143,10 @@ def get_postfix_expression(expression):
def is_number(char): def is_number(char):
try: try:
float(char);return True float(char)
except ValueError: return False return True
except ValueError:
return False
for char in expression: for char in expression:
if is_number(char): if is_number(char):
@ -153,7 +161,6 @@ def get_postfix_expression(expression):
while stack and stack[-1] != '(' and precedence.get(stack[-1], 0) >= precedence.get(char, 0): while stack and stack[-1] != '(' and precedence.get(stack[-1], 0) >= precedence.get(char, 0):
postfix.append(stack.pop()) postfix.append(stack.pop())
stack.append(char) stack.append(char)
while stack: while stack:
postfix.append(stack.pop()) postfix.append(stack.pop())
@ -193,7 +200,7 @@ def calculate(root, TreeNode): # 计算节点树表达式
elif root.Ops == '/': elif root.Ops == '/':
if right_value == 0: if right_value == 0:
return None # 除数为0返回None表示计算错误 return None # 除数为0返回None表示计算错误
return left_value / right_value return left_value / right_value # 除法结果为浮点数
return None # 节点类型不合法返回None表示计算错误 return None # 节点类型不合法返回None表示计算错误
@ -202,6 +209,8 @@ def find_node_by_id(node_id, TreeNode):
if node.NodeID == node_id: if node.NodeID == node_id:
return node return node
return None return None
def evaluate_postfix(expression): # 计算后缀表达式 def evaluate_postfix(expression): # 计算后缀表达式
stack = [] stack = []
for char in expression: for char in expression:
@ -223,6 +232,7 @@ def evaluate_postfix(expression): # 计算后缀表达式
stack.append(result) stack.append(result)
return stack.pop() return stack.pop()
def exp_to_treeNode_dict(exp_ls): # 返回嵌套节点字典 def exp_to_treeNode_dict(exp_ls): # 返回嵌套节点字典
stack = [] stack = []
for char in exp_ls: for char in exp_ls:
@ -233,11 +243,28 @@ def exp_to_treeNode_dict(exp_ls): # 返回嵌套节点字典
right = stack.pop() right = stack.pop()
left = stack.pop() left = stack.pop()
root = char root = char
two[root] = [left,right] two[root] = [left, right]
stack.append(two) stack.append(two)
return stack.pop() return stack.pop()
# 写一个函数从TreeNode中还原出表达式
def get_expression(TreeNode):
stack = []
for node in TreeNode:
if node.NodeType == 'Value':
stack.append(node.FaceValue)
elif node.NodeType == 'Operator':
if node.Ops in ('sin', 'cos', 'tan'): # 三角函数
right = stack.pop() # 三角函数只有右操作数
stack.append(f"{node.Ops}({right})")
else:
right = stack.pop()
left = stack.pop()
stack.append(f"({left}{node.Ops}{right})")
return stack.pop()
def ExpressionAnalyse(exp_ls): # 返回语法树 def ExpressionAnalyse(exp_ls): # 返回语法树
stack = [] # 符合和数值栈 stack = [] # 符合和数值栈
TreeNode = [] TreeNode = []
@ -310,7 +337,7 @@ if __name__ == '__main__':
# print(exp_to_treeNode_dict(exp_ls)) # print(exp_to_treeNode_dict(exp_ls))
# exp_ls = ['3.3', '2', '^', '3', '3', '*', '-'] # exp_ls = ['3.3', '2', '^', '3', '3', '*', '-']
TreeNode= ExpressionAnalyse(exp_ls) TreeNode = ExpressionAnalyse(exp_ls)
result = calculate(TreeNode[-1], TreeNode) result = calculate(TreeNode[-1], TreeNode)
print(result) print(result)
@ -319,5 +346,4 @@ if __name__ == '__main__':
for node in TreeNode: for node in TreeNode:
print(node) print(node)
# print_tree(Aexp)
# print_tree(Aexp)

@ -6,6 +6,7 @@ from PySide6.QtWidgets import QGraphicsItem
class RoundedRectangleItem(QGraphicsItem, QObject): class RoundedRectangleItem(QGraphicsItem, QObject):
selected = Signal(int) selected = Signal(int)
unselected = Signal(int) unselected = Signal(int)
def __init__(self, x, y, text, id): def __init__(self, x, y, text, id):
QGraphicsItem.__init__(self) QGraphicsItem.__init__(self)
QObject.__init__(self) QObject.__init__(self)
@ -65,5 +66,4 @@ class RoundedRectangleItem(QGraphicsItem, QObject):
else: else:
self.unselected.emit(self.id) self.unselected.emit(self.id)
super().mousePressEvent(event) super().mousePressEvent(event)

@ -1,11 +1,11 @@
import random import random
from PySide6.QtGui import QPainter, QPen, QFont, QPixmap
from PySide6.QtGui import QFont
from PySide6.QtWidgets import QApplication, QMainWindow, QGraphicsLineItem, QMessageBox, QGraphicsScene from PySide6.QtWidgets import QApplication, QMainWindow, QGraphicsLineItem, QMessageBox, QGraphicsScene
from main_ui import Ui_MainWindow
import data import data
from graph_24 import * from graph_24 import *
from main_ui import Ui_MainWindow
class MainWindow(QMainWindow, Ui_MainWindow): class MainWindow(QMainWindow, Ui_MainWindow):
@ -27,37 +27,36 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.setupUi(self) self.setupUi(self)
self.init_ui() self.init_ui()
self.init_slot() self.init_slot()
self.pushButton_q.clicked.connect(self.show_card) self.pushButton_q.clicked.connect(self.show_card) # 显示卡片
self.pushButton_ex.clicked.connect(self.show_card) self.pushButton_ex.clicked.connect(self.show_card) # 显示卡片
self.pushButton_autosv.clicked.connect(self.AutoTest_9_10) self.pushButton_autosv.clicked.connect(self.AutoTest_9_10) # 自动求解
self.pushButton_dtree.clicked.connect(self.draw_tree) self.pushButton_dtree.clicked.connect(self.draw_tree) # 绘制语法树
self.pushButton_ast.clicked.connect(self.calculate_button) self.pushButton_ast.clicked.connect(self.calculate_button) # 生成语法树
self.pushButton_allan.clicked.connect(self.AutoTest) self.pushButton_allan.clicked.connect(self.AutoTest) # 自动求解
self.clear_button.clicked.connect(self.secen_clear) self.clear_button.clicked.connect(self.secen_clear) # 清空画布
self.pushButton_add.clicked.connect(lambda :self.select_ops('+')) self.pushButton_add.clicked.connect(lambda: self.select_ops('+'))
self.pushButton_sub.clicked.connect(lambda :self.select_ops('-')) self.pushButton_sub.clicked.connect(lambda: self.select_ops('-'))
self.pushButton_mul.clicked.connect(lambda :self.select_ops('*')) self.pushButton_mul.clicked.connect(lambda: self.select_ops('*'))
self.pushButton_div.clicked.connect(lambda :self.select_ops('/')) self.pushButton_div.clicked.connect(lambda: self.select_ops('/'))
self.add_val_node.clicked.connect(self.add_value_node) self.add_val_node.clicked.connect(self.add_value_node) # 添加数值节点
self.add_ops_node.clicked.connect(self.add_operator_node) self.add_ops_node.clicked.connect(self.add_operator_node) # 添加运算符节点
self.ex_node_value.clicked.connect(self.exchange_value_node) self.ex_node_value.clicked.connect(self.exchange_value_node) # 修改数值节点
self.ex_node_ops.clicked.connect(self.exchange_ops_node) self.ex_node_ops.clicked.connect(self.exchange_ops_node) # 修改运算符节点
self.ex_node_self.clicked.connect(self.exchange_two_nodes) self.ex_node_self.clicked.connect(self.exchange_two_nodes) # 交换两个节点
self.pushButton_exp.clicked.connect(self.agent_exp) # 生成表达式
def secen_clear(self): def secen_clear(self):
self.scene.clear() self.scene.clear()
self.selected_id = [] self.selected_id = [] # 选中的节点ID
self.value_nodes = [] self.value_nodes = [] # 数值节点
self.TreeNode = [] self.TreeNode = [] # 所有节点
self.adds_id = set() self.adds_id = set() # 已经用过的ID
self.trees_root = [] self.trees_root = [] # 保存所有树的根节点
self.drawn_tree_id = set() self.drawn_tree_id = set() # 已经绘制了树的节点
self.selected_value = None # 当前选择的卡片值. self.selected_value = None # 当前选择的卡片值.
self.selected_ops = None # 选择的运算符 self.selected_ops = None # 选择的运算符
# 清空运算符显示 # 清空运算符显示
self.lb_ops_selected.setText("") self.lb_ops_selected.setText("") # 运算符显示
def select_ops(self, ops): def select_ops(self, ops):
self.lb_ops_selected.setText(ops) self.lb_ops_selected.setText(ops)
@ -67,10 +66,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# self.scene.clear() # self.scene.clear()
if self.selected_value is not None: # 选择了卡片值 if self.selected_value is not None: # 选择了卡片值
self.value_nodes.append(self.selected_value) # 添加到节点数值列表 self.value_nodes.append(self.selected_value) # 添加到节点数值列表
for i in range(len(self.adds_id)+1): for i in range(len(self.adds_id) + 1):
if i not in self.adds_id: if i not in self.adds_id:
value = self.selected_value value = self.selected_value
nodet = RoundedRectangleItem(150*self.seq, 0, str(value), i) nodet = RoundedRectangleItem(150 * self.seq, 0, str(value), i)
self.seq += 1 # 序号加1 self.seq += 1 # 序号加1
nodet.selected.connect(lambda id: self.selected_node(id)) # 连接信号 nodet.selected.connect(lambda id: self.selected_node(id)) # 连接信号
nodet.unselected.connect(lambda id: self.unselected_node(id)) nodet.unselected.connect(lambda id: self.unselected_node(id))
@ -87,14 +86,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
if node.LeftNodeID == id or node.RightNodeID == id: if node.LeftNodeID == id or node.RightNodeID == id:
return True return True
def add_operator_node(self): def add_operator_node(self): # 添加运算符节点
if self.selected_ops is not None: if self.selected_ops is not None:
if len(self.selected_id) == 2: if len(self.selected_id) == 2:
# 判断已选节点是否已经被连接 # 判断已选节点是否已经被连接
if self.judge_node_conn(): if self.judge_node_conn():
QMessageBox.warning(self, '警告', '节点已经连接') QMessageBox.warning(self, '警告', '节点已经连接')
return return
for i in range(len(self.adds_id)+1): # 确保id唯一 for i in range(len(self.adds_id) + 1): # 确保id唯一
if i not in self.adds_id: if i not in self.adds_id:
node = data.Node([i, 'Operator', self.selected_ops, None, None, None, None]) node = data.Node([i, 'Operator', self.selected_ops, None, None, None, None])
self.TreeNode.append(node) self.TreeNode.append(node)
@ -119,12 +118,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
for i, root in enumerate(self.trees_root): for i, root in enumerate(self.trees_root):
if self.has_both_operators(self.TreeNode): if self.has_both_operators(self.TreeNode):
self.offset = 35 self.offset = 35
self.ShowTree(root, self.TreeNode,i*300, 0) self.ShowTree(root, self.TreeNode, i * 300, 0)
self.offset = 0 self.offset = 0
self.seq = 1 # 重置序号 self.seq = 1 # 重置序号
for noed in self.TreeNode: for noed in self.TreeNode:
print("运算符节点", noed) print("运算符节点", noed)
exps = data.get_expression(self.TreeNode)
print("表达式", exps)
else: else:
QMessageBox.warning(self, '警告', '请先选择两个节点') QMessageBox.warning(self, '警告', '请先选择两个节点')
else: else:
@ -200,7 +201,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
else: else:
QMessageBox.warning(self, '警告', '请选择两个节点') QMessageBox.warning(self, '警告', '请选择两个节点')
def selected_node(self, id): def selected_node(self, id):
if len(self.selected_id) < 2: if len(self.selected_id) < 2:
self.selected_id.append(id) self.selected_id.append(id)
@ -212,7 +212,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
nodet.isSelected = False # 取消选中 nodet.isSelected = False # 取消选中
nodet.update() # 更新图元 nodet.update() # 更新图元
def unselected_node(self, id): def unselected_node(self, id):
self.selected_id.remove(id) self.selected_id.remove(id)
print(self.selected_id) print(self.selected_id)
@ -223,11 +222,11 @@ class MainWindow(QMainWindow, Ui_MainWindow):
if nodet.id == id: # 如果是当前选中的节点 if nodet.id == id: # 如果是当前选中的节点
nodet.isSelected = False # 取消选中 nodet.isSelected = False # 取消选中
nodet.update() # 更新图元 nodet.update() # 更新图元
def init_ui(self): def init_ui(self):
self.scene = QGraphicsScene() self.scene = QGraphicsScene()
self.graphicsView.setScene(self.scene) self.graphicsView.setScene(self.scene)
def init_slot(self): def init_slot(self):
self.pushButton.clicked.connect(self.on_calc) self.pushButton.clicked.connect(self.on_calc)
@ -239,21 +238,20 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.pushButton_allan.setEnabled(False) self.pushButton_allan.setEnabled(False)
self.pushButton_dtree.setEnabled(False) self.pushButton_dtree.setEnabled(False)
self.pushButton_autosv.setEnabled(False) self.pushButton_autosv.setEnabled(False)
print(value) # print(value)
if index == 0: if index == 0:
self.p1.setStyleSheet(f"border-image: url({path});") self.p1.setStyleSheet(f"border-image: url({path});")
self.p1.clicked.connect(lambda :current_selection(Tree_4_nums[index], path)) self.p1.clicked.connect(lambda: current_selection(Tree_4_nums[index], path))
elif index == 1: elif index == 1:
self.p2.setStyleSheet(f"border-image: url({path});") self.p2.setStyleSheet(f"border-image: url({path});")
self.p2.clicked.connect(lambda :current_selection(Tree_4_nums[index], path)) self.p2.clicked.connect(lambda: current_selection(Tree_4_nums[index], path))
elif index == 2: elif index == 2:
self.p3.setStyleSheet(f"border-image: url({path});") self.p3.setStyleSheet(f"border-image: url({path});")
self.p3.clicked.connect(lambda :current_selection(Tree_4_nums[index], path)) self.p3.clicked.connect(lambda: current_selection(Tree_4_nums[index], path))
elif index == 3: elif index == 3:
self.p4.setStyleSheet(f"border-image: url({path});") self.p4.setStyleSheet(f"border-image: url({path});")
self.p4.clicked.connect(lambda :current_selection(Tree_4_nums[index], path)) self.p4.clicked.connect(lambda: current_selection(Tree_4_nums[index], path))
def show_card(self): def show_card(self):
self.pushButton_ast.setEnabled(True) self.pushButton_ast.setEnabled(True)
@ -319,22 +317,22 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.on_calc() # 自动计算 self.on_calc() # 自动计算
self.draw_tree() # 绘制语法树 self.draw_tree() # 绘制语法树
def calculate_button(self): # def calculate_button(self): # 计算生成语法树
self.scene.clear() self.scene.clear()
aexp = self.lineEdit.text() aexp = self.lineEdit.text()
try: try:
exp_ls = data.get_postfix_expression(aexp) # 获取后缀表达式列表 exp_ls = data.get_postfix_expression(aexp) # 获取后缀表达式列表
self.TreeNode = data.ExpressionAnalyse(exp_ls) # 将后缀表达式转化为节点树 self.TreeNode = data.ExpressionAnalyse(exp_ls) # 将后缀表达式转化为节点树
result = data.calculate(self.TreeNode[-1], self.TreeNode) result = data.calculate(self.TreeNode[-1], self.TreeNode)
self.label_result.setText(f"={result}") self.label_result.setText(f"={round(result, 2)}")
except: except:
QMessageBox.warning(self, '警告', '表达式错误!') QMessageBox.warning(self, '警告', '表达式错误!')
return return
if self.TreeNode: if self.TreeNode: # 如果节点树不为空
root = self.TreeNode[-1] root = self.TreeNode[-1]
result = data.calculate(root, self.TreeNode) result = data.calculate(root, self.TreeNode) # 计算表达式的值
self.label_result.setText(f"={result}") self.label_result.setText(f"={round(result, 2)}")
self.result_ToF(int(result)) self.result_ToF(int(result)) # 判断结果是否为24
if self.has_both_operators(self.TreeNode): if self.has_both_operators(self.TreeNode):
self.offset = 35 self.offset = 35
self.ShowTree(root, self.TreeNode) self.ShowTree(root, self.TreeNode)
@ -342,10 +340,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def has_both_operators(self, TreeNode): # 判断是否同时有两个运算符 def has_both_operators(self, TreeNode): # 判断是否同时有两个运算符
ops = data.OPS ops = data.OPS
def find_op_by_id(id): # 根据ID查找运算符 def find_op_by_id(id): # 根据ID查找运算符
for node in TreeNode: for node in TreeNode:
if node.NodeID == id and node.NodeType == "Operator": if node.NodeID == id and node.NodeType == "Operator":
return node.Ops return node.Ops
for node in TreeNode: # 遍历节点树 for node in TreeNode: # 遍历节点树
if node.NodeType == "Operator": if node.NodeType == "Operator":
opl = find_op_by_id(node.LeftNodeID) opl = find_op_by_id(node.LeftNodeID)
@ -353,8 +353,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
if opl in ops and opr in ops: if opl in ops and opr in ops:
return True return True
def draw_tree(self): def draw_tree(self):
self.scene.clear() self.scene.clear()
aexp = self.lineEdit.text() aexp = self.lineEdit.text()
@ -372,25 +370,27 @@ class MainWindow(QMainWindow, Ui_MainWindow):
except Exception as e: except Exception as e:
QMessageBox.warning(self, '警告', '表达式错误') QMessageBox.warning(self, '警告', '表达式错误')
def ShowTree(self, root, TreeNode, startx=0, starty=0, depth=0): def ShowTree(self, root, TreeNode, startx=0, starty=0, depth=0):
self.selected_id = [] # 清空选中的节点
self.drawn_tree_id = set() # 清空已绘制的节点ID
# 绘制根节点 # 绘制根节点
if root.NodeType == 'Value': if root.NodeType == 'Value':
nds_root = RoundedRectangleItem(startx, starty, root.FaceValue, root.NodeID) nds_root = RoundedRectangleItem(startx, starty, root.FaceValue, root.NodeID)
nds_root.selected.connect(lambda id: self.selected_node(id)) nds_root.selected.connect(lambda id: self.selected_node(id))
nds_root.unselected.connect(lambda id: self.unselected_node(id)) nds_root.unselected.connect(lambda id: self.unselected_node(id))
self.drawn_tree_id.add(root.NodeID) self.drawn_tree_id.add(root.NodeID)
self.adds_id.add(root.NodeID)
else: else:
nds_root = RoundedRectangleItem(startx, starty, root.Ops, root.NodeID) nds_root = RoundedRectangleItem(startx, starty, root.Ops, root.NodeID)
nds_root.selected.connect(lambda id: self.selected_node(id)) nds_root.selected.connect(lambda id: self.selected_node(id))
nds_root.unselected.connect(lambda id: self.unselected_node(id)) nds_root.unselected.connect(lambda id: self.unselected_node(id))
self.drawn_tree_id.add(root.NodeID) self.drawn_tree_id.add(root.NodeID)
self.adds_id.add(root.NodeID)
nds_root.setZValue(1) nds_root.setZValue(1)
self.scene.addItem(nds_root) self.scene.addItem(nds_root)
# 计算节点间的水平偏移量 # 计算节点间的水平偏移量
horizontal_offset = 100 - depth*self.offset horizontal_offset = 100 - depth * self.offset
# 计算左子树和右子树的位置 # 计算左子树和右子树的位置
left_x, left_y = startx - horizontal_offset, starty + 100 left_x, left_y = startx - horizontal_offset, starty + 100
@ -418,7 +418,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
line_right.setPen(QPen(Qt.red, 3)) line_right.setPen(QPen(Qt.red, 3))
self.scene.addItem(line_right) self.scene.addItem(line_right)
def on_calc(self): def on_calc(self):
aexp = self.lineEdit.text() aexp = self.lineEdit.text()
if aexp == '': if aexp == '':
@ -433,8 +432,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
QMessageBox.warning(self, '警告', '表达式错误') QMessageBox.warning(self, '警告', '表达式错误')
return return
def result_ToF(self, result):
def result_ToF(self,result):
font = QFont('Microsoft YaHei', 16) font = QFont('Microsoft YaHei', 16)
font.setBold(True) # 将字体设置为粗体 font.setBold(True) # 将字体设置为粗体
self.label_TF.setText('' if result == 24 else '×') self.label_TF.setText('' if result == 24 else '×')
@ -443,6 +441,18 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# 将文本颜色设置为红色 # 将文本颜色设置为红色
self.label_TF.setStyleSheet("color: red;background-color:rgb(219, 205, 166)") self.label_TF.setStyleSheet("color: red;background-color:rgb(219, 205, 166)")
def agent_exp(self):
if self.TreeNode is not None:
exp_str = data.get_expression(self.TreeNode)
if exp_str is not None:
self.label_result.clear() # 清空显示结果
self.lineEdit.clear() # 清空显示表达式
self.lineEdit.setText(exp_str) # 显示表达式
else:
QMessageBox.warning(self, '警告', '无法生成表达式')
else:
QMessageBox.warning(self, '警告', '当前无语法树')
if __name__ == '__main__': if __name__ == '__main__':
app = QApplication() app = QApplication()

Loading…
Cancel
Save