需要有关 QlistWidget.data() 问题的帮助

问题描述 投票:0回答:1

每个任务项都包含操作列表我使用 QlistWidgetItem[] 来保存它 如果我单击任务项。操作视图区域可以从taskitem.data()重新加载数据。 当任务中的每个项目都没有操作数据时,当您切换任务项目时,程序不会崩溃。 当只有一个带有操作数据的任务项时不会崩溃 但是当您切换具有操作数据的任务项时,程序会崩溃。 enter image description here

# This Python file uses the following encoding: utf-8
import sys
import copy

from PySide6.QtCore import Signal, Slot, QRect, Qt, QPoint
from PySide6.QtGui import QPalette, QColor, QMouseEvent, QPen, QPainter
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout, QListWidgetItem

# Important:
# You need to run the following command to generate the ui_form.py file
#     pyside6-uic form.ui -o ui_form.py, or
#     pyside2-uic form.ui -o ui_form.py
from ui_form import Ui_MainWindow

from datamanager import ActionData
from newtaskdialog import NewTaskDialog
from newmouseactiondialog import NewMouseActionDialog

class Rect:
    def __init__(self, rect: QRect):
        self._rect = rect
        self._is_hover = False
        self._is_drag = False
        self._is_edge_drag = False

class RenderArea(QWidget):
    signal_move_event = Signal(QMouseEvent)
    signal_release_event = Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMouseTracking(True)
        self._mouse_x = 0
        self._mouse_y = 0

        self._previous_mouse_pos = None

        # 初始绘图相关
        self.pen = QPen(Qt.blue, 3)

        self.rect_list = []

    def isRectIncludeMouse(self, mouse_pos: QPoint, rect: QRect):
        cursor_x = mouse_pos.x()
        cursor_y = mouse_pos.y()
        edge_weight = 8
        if(cursor_x >= rect.x()
           and cursor_x <= rect.x() + rect.width() - edge_weight
           and cursor_y >= rect.y()
           and cursor_y <= rect.y() + rect.height() - edge_weight
           ):
            return True
        else:
            return False

    def isMouseOnRectEdge(self, mouse_pos: QPoint, rect: QRect):
        cursor_x = mouse_pos.x()
        cursor_y = mouse_pos.y()
        edge_weight = 8
        if(cursor_x <= rect.x() + rect.width()
           and cursor_x > rect.x() + rect.width() - edge_weight
           and cursor_y <= rect.y() + rect.height()
           and cursor_y > rect.y() + rect.height() - edge_weight
           ):
            return True
        else:
            return False

    def mousePressEvent(self, event: QMouseEvent):
        self._previous_mouse_pos = event.position().toPoint()
        is_there_one_drag = False
        is_there_one_edge_drag = False
        for rect_index in range(len(self.rect_list)):
            if (self.isRectIncludeMouse(event.position().toPoint(), self.rect_list[rect_index]._rect)
            and not is_there_one_drag):
                self.rect_list[rect_index]._is_drag = True
                is_there_one_drag = True
            elif(self.isMouseOnRectEdge(event.position().toPoint(), self.rect_list[rect_index]._rect)
            and not is_there_one_edge_drag):
                self.rect_list[rect_index]._is_edge_drag = True
                is_there_one_edge_drag = True

    def mouseReleaseEvent(self, event: QMouseEvent):
        for rect_index in range(len(self.rect_list)):
            self.rect_list[rect_index]._is_drag = False
            self.rect_list[rect_index]._is_edge_drag = False
        self.signal_release_event.emit()

    def mouseMoveEvent(self, event: QMouseEvent):
        for rect_index in range(len(self.rect_list)):
            if self.rect_list[rect_index]._is_drag:
                new_rect_x = (event.position().x() - self._previous_mouse_pos.x()) + self.rect_list[rect_index]._rect.x()
                new_rect_y = (event.position().y() - self._previous_mouse_pos.y()) + self.rect_list[rect_index]._rect.y()
                if new_rect_x >= 0 and  new_rect_x <= self.width():
                    self.rect_list[rect_index]._rect.moveTo(new_rect_x, self.rect_list[rect_index]._rect.y())
                if new_rect_y >= 0 and new_rect_y <= self.height():
                    self.rect_list[rect_index]._rect.moveTo(self.rect_list[rect_index]._rect.x(), new_rect_y)
                self._previous_mouse_pos = event.position().toPoint()
            elif self.rect_list[rect_index]._is_edge_drag:
                new_rect_widght = (event.position().x() - self._previous_mouse_pos.x()) + self.rect_list[rect_index]._rect.width()
                new_rect_height = (event.position().y() - self._previous_mouse_pos.y()) + self.rect_list[rect_index]._rect.height()
                if new_rect_widght < 16:
                    new_rect_widght = 16
                if new_rect_height < 16:
                    new_rect_height = 16
                self.rect_list[rect_index]._rect.setWidth(new_rect_widght)
                self.rect_list[rect_index]._rect.setHeight(new_rect_height)
                self._previous_mouse_pos = event.position().toPoint()
        self.update()
        self.signal_move_event.emit(event)
        QWidget.mouseMoveEvent(self, event)

    def paintEvent(self, event):
        # 绘制一个矩形
        with QPainter(self) as painter:
            painter.setPen(self.pen)
            for rect in self.rect_list:
                if rect._is_hover:
                    painter.save()
                    pen = QPen(Qt.red, 3)
                    painter.setPen(pen)
                    painter.drawRect(rect._rect)
                    painter.restore()
                else:
                    painter.drawRect(rect._rect)
        # 碰撞检查

        # 拖动

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # new action type dick
        self.action_type_dict = {
            "启动游戏": 0,
            "释放游戏": 1,
            "鼠标": 2,
            "键盘": 3,
        }

        # self.setMouseTracking(True)
        self._NewTaskDialog = NewTaskDialog()
        self._NewTaskDialog.hide()

        self._new_mouse_action_dialog = NewMouseActionDialog()
        self._new_mouse_action_dialog.hide()

        # 绘制区域初始化
        self._render_area = RenderArea()
        # 设置背景颜色
        back_ground_palette = QPalette()
        back_ground_palette.setColor(QPalette.Window, QColor(200, 200, 200))
        self._render_area.setPalette(back_ground_palette)
        self._render_area.setAutoFillBackground(True)
        # 设置布局,加入父窗口
        right_widget_layout = QHBoxLayout()
        right_widget_layout.addWidget(self._render_area)
        self.ui.widget_right.setLayout(right_widget_layout)

        # 新建 Task slot
        self.ui.pushButtonNewTask.clicked.connect(self.OpenNewTaskDialog)
        # 编辑 Task
        self.ui.listWidgetTaskList.itemDoubleClicked.connect(self.OpenEditTaskDialog)
        self.ui.listWidgetTaskList.itemClicked.connect(self.TaskItemSelected)
        # delete Task
        self.ui.pushButtonDeleteTask.clicked.connect(self.DeleteTask)
        # 添加或修改 Task slot
        self._NewTaskDialog.signal_add_clicked.connect(self.AddNewTask)
        self._NewTaskDialog.signal_edit_clicked.connect(self.EditTask)
        # Move up or Move Down Task slot
        self.ui.pushButtonTaskMoveUp.clicked.connect(self.TaskMoveUp)
        self.ui.pushButtonTaskMoveDown.clicked.connect(self.TaskMoveDown)

        # new action slot
        self.ui.pushButtonNewAction.clicked.connect(self.OpenNewActionDialog)
        self.ui.listWidgetActionList.itemDoubleClicked.connect(self.OpenEditActionDialog)
        self.ui.pushButtonDeleteAction.clicked.connect(self.DeleteAction)
        self.ui.listWidgetActionList.itemClicked.connect(self.ActionItemSelected)

        # new mouse action slot
        self._new_mouse_action_dialog.signal_add_confirm_clicked.connect(self.AddMouseAction)
        self._new_mouse_action_dialog.signal_edit_confirm_clicked.connect(self.EditMouseAction)

        # Move up and Move down action slot
        self.ui.pushButtonActionMoveUp.clicked.connect(self.ActionMoveUp)
        self.ui.pushButtonActionMoveDown.clicked.connect(self.ActionMoveDown)

        #update mouse position
        self._render_area.signal_move_event.connect(self.UpdateStatus)
        self._render_area.signal_release_event.connect(self.SaveRect)

    @Slot()
    def OpenNewTaskDialog(self):
        self._NewTaskDialog.OpenNewDialog()

    @Slot()
    def OpenEditTaskDialog(self):
        self._NewTaskDialog.OpenEditDialog(self.ui.listWidgetTaskList.currentItem().text())

    @Slot()
    def TaskItemSelected(self):
        current_item = self.ui.listWidgetTaskList.currentItem()
        action_data_list = current_item.data(Qt.UserRole)
        for i in range(self.ui.listWidgetActionList.count()):
            self.ui.listWidgetActionList.takeItem(0)
        for action_data in action_data_list:
            self.ui.listWidgetActionList.addItem(action_data)

    @Slot()
    def DeleteTask(self):
        current_row = self.ui.listWidgetTaskList.currentRow()
        if self.ui.listWidgetTaskList.count() > 0 and current_row >= 0:
            self.ui.listWidgetTaskList.takeItem(current_row)

    @Slot()
    def AddNewTask(self, name: str):
        item = QListWidgetItem()
        item.setText(name)
        action_data_list: List[QListWidgetItem] = []
        item.setData(Qt.UserRole, action_data_list)
        self.ui.listWidgetTaskList.addItem(item)

    @Slot()
    def EditTask(self, name: str):
        currenttask = self.ui.listWidgetTaskList.currentItem()
        currenttask.setText(name)
        self.ui.listWidgetTaskList.setCurrentItem(currenttask)

    @Slot()
    def TaskMoveUp(self):
        current_row = self.ui.listWidgetTaskList.currentRow()
        if current_row > 0 and self.ui.listWidgetTaskList.count() > 0:
            above_item = self.ui.listWidgetTaskList.takeItem(current_row - 1)
            self.ui.listWidgetTaskList.insertItem(current_row, above_item)

    @Slot()
    def TaskMoveDown(self):
        current_row = self.ui.listWidgetTaskList.currentRow()
        if current_row < self.ui.listWidgetTaskList.count() - 1 and self.ui.listWidgetTaskList.count() > 0:
            below_item = self.ui.listWidgetTaskList.takeItem(current_row + 1)
            self.ui.listWidgetTaskList.insertItem(current_row, below_item)

    @Slot()
    def OpenNewActionDialog(self):
        current_action_type = self.action_type_dict[self.ui.comboBoxActionType.currentText()]
        if current_action_type == self.action_type_dict["启动游戏"]:
            pass
        elif current_action_type == self.action_type_dict["释放游戏"]:
            pass
        elif current_action_type == self.action_type_dict["鼠标"]:
            self._new_mouse_action_dialog.OpenNewDialog()

    @Slot()
    def OpenEditActionDialog(self):
        currentItem = self.ui.listWidgetActionList.currentItem()
        action_data = currentItem.data(Qt.UserRole)
        if action_data._action_type == self.action_type_dict["鼠标"]:
            self._new_mouse_action_dialog.OpenEditDialog(action_data._mouse_action_data._mouse_action_type, action_data._mouse_action_data._timer)

    @Slot()
    def DeleteAction(self):
        current_row = self.ui.listWidgetActionList.currentRow()
        if self.ui.listWidgetActionList.count() > 0 and current_row >= 0:
            self.ui.listWidgetActionList.takeItem(current_row)
            self._render_area.rect_list.clear()
            self._render_area.update()

    @Slot()
    def ActionItemSelected(self):
        currentItem = self.ui.listWidgetActionList.currentItem()
        mouse_action_data = currentItem.data(Qt.UserRole)._mouse_action_data
        rect = Rect(QRect(mouse_action_data._x, mouse_action_data._y, mouse_action_data._width, mouse_action_data._height))
        self._render_area.rect_list.clear()
        self._render_area.rect_list.append(rect)
        self._render_area.update()

    @Slot()
    def AddMouseAction(self, mouseactiondata):
        action_data = ActionData()
        action_data._action_type = self.action_type_dict["鼠标"]
        action_data._mouse_action_data = mouseactiondata
        item = QListWidgetItem()
        item.setText(mouseactiondata._mouse_action_name)
        item.setData(Qt.UserRole, action_data)
        self.ui.listWidgetActionList.addItem(item)
        #save
        self.SaveActionList()

    @Slot()
    def EditMouseAction(self, mouseactiondata):
        currentItem = self.ui.listWidgetActionList.currentItem()
        action_data = currentItem.data(Qt.UserRole)
        action_data._mouse_action_data._mouse_action_type = mouseactiondata._mouse_action_type
        action_data._mouse_action_data._mouse_action_name = mouseactiondata._mouse_action_name
        action_data._mouse_action_data._timer = mouseactiondata._timer

        currentItem.setData(Qt.UserRole, action_data)
        currentItem.setText(action_data._mouse_action_data._mouse_action_name)
        self.ui.listWidgetActionList.setCurrentItem(currentItem)

    @Slot()
    def ActionMoveUp(self):
        current_row = self.ui.listWidgetActionList.currentRow()
        if current_row > 0 and self.ui.listWidgetActionList.count() > 0:
            above_item = self.ui.listWidgetActionList.takeItem(current_row - 1)
            self.ui.listWidgetActionList.insertItem(current_row, above_item)

    @Slot()
    def ActionMoveDown(self):
        current_row = self.ui.listWidgetActionList.currentRow()
        if current_row < self.ui.listWidgetActionList.count() - 1 and self.ui.listWidgetActionList.count() > 0:
            below_item = self.ui.listWidgetActionList.takeItem(current_row + 1)
            self.ui.listWidgetActionList.insertItem(current_row, below_item)

    @Slot()
    def UpdateStatus(self, event: QMouseEvent):
        pos_x = int(event.position().x())
        pos_y = int(event.position().y())
        str_pos = f"X:{pos_x} Y:{pos_y}"
        self.ui.statusbar.showMessage(str_pos)
        # print(f"X:{pos_x}, Y:{pos_y}")

    def SaveActionList(self):
        action_data_list = []
        for row in range(self.ui.listWidgetActionList.count()):
            item = self.ui.listWidgetActionList.item(row)
            action_data_list.append(item)
        currenttask = self.ui.listWidgetTaskList.currentItem()
        currenttask.setData(Qt.UserRole, action_data_list)
        self.ui.listWidgetTaskList.setCurrentItem(currenttask)

不知道如何解决

python pyqt crash pyside6
1个回答
0
投票

您在选择项目时似乎遇到了此错误。当您选择可以使用的物品时捕捉

if currentItem:
      ....

这样您就可以确定该项目是否可用(或存在)。在您的

ActionItemSelected
函数中检查这一点。另外,qt 拥有您使用的大部分插槽。你正在为自己创造不必要的工作

© www.soinside.com 2019 - 2024. All rights reserved.