鱼C论坛

 找回密码
 立即注册
查看: 1069|回复: 8

[Python,Pyqt]这里可以发悬赏帖吗?有偿修改代码,重写QComboBox委托,50-100左右

[复制链接]
发表于 2023-7-7 10:43:30 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
昨天发帖学习了委托,实验了以后实在是写不出来,老报错。想花钱请人帮忙,我自己顺便再跟着代码学一下

                               
登录/注册后可看大图


                               
登录/注册后可看大图

需求:
点修改按钮,TableView,第1,2列可编辑   (已实现)
双击price后,price清空,输入金额,sql会匹配,有返回值。就把返回值传给ComboBox,并将ComboBox显示在【挂号等级type】列。(未实现)
无返回值,则提示“没有价格为{price}的号”(已实现)

目前未完成的代码如下:

from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
import sys
import Dbconnect
import MenuWindow
import CliPriceModifyWindow

class MenuWindow(MenuWindow.Ui_MainWindow,QMainWindow):
    def __init__(self):
        super(MenuWindow, self).__init__()
        self.setupUi(self)
        #定义QAction触发逻辑
        self.clipricemodi_window = CliPriceModifyWindow()
        self.actprice.triggered.connect(self.actprice_open)
        self.mExit.aboutToShow.connect(sys.exit)

    def actprice_open(self):
        a = self.windowTitle()
        if (a.split()[2] == '门诊办'):
            self.clipricemodi_window.show()
        else:
            QMessageBox.critical(self, '没有操作权限', '您不是门诊办人员!')

#重写ComboBox委托
class ComboBoxDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super(ComboBoxDelegate, self).__init__(parent)

    def createEditor(self, parent, option, index):
        editor = QComboBox(parent)
        return editor

    def setEditorData(self, editor, index):
        # 这个函数用来设置编辑器的数据
        price = index.model().data(index, Qt.ItemDataRole.DisplayRole)
        sqlprice = "SELECT C.CLINIC_TYPE FROM  (SELECT A.CLINIC_TYPE,SUM(B.PRICE) AS PRICE " \
                    "FROM CLINIC_TYPE_SETTING A,CURRENT_PRICE_LIST B  " \
                    "WHERE A.PRICE_ITEM=B.ITEM_CODE  GROUP BY A.CLINIC_TYPE) C " \
                    "WHERE C.PRICE='{price}'".format(price=price)
        Dbconnect.cursor.execute(sqlprice)
        sqlprice_result = Dbconnect.cursor.fetchall()
        # 添加到ComboBox中
        for i in sqlprice_result:
            editor.addItem(str(i))
        # 设置当前选中的项
        editor.setCurrentIndex(editor.findText(price))

    def setModelData(self, editor, model, index):
        # 当编辑器关闭时,将编辑器的数据写入模型
        value = editor.currentText()
        model.setData(index, value, Qt.EditRole)

    #触发事件:【价格price】变化,【挂号等级type】同步更新并传入ComboBox,类似触发器
    def onDataChanged(self, index):
        pass
        这一块还没写,不会写


#门诊办专区号表价格修改
class CliPriceModifyWindow(CliPriceModifyWindow.Ui_Form,QWidget):
    def __init__(self):
        super(CliPriceModifyWindow, self).__init__()
        self.setupUi(self)
        self.pBtnQuery.clicked.connect(self.cliprice_query)
        self.pBtnModify.clicked.connect(self.cliprice_modify)
        self.pBtnSave.clicked.connect(self.cliprice_save)
        self.pBtnReset.clicked.connect(self.cliprice_reset)

        # 号表查询  (此部分已正常实现)
    def cliprice_query(self):
        # 通过号表查询
        cliniclabel = self.lineEditClinic.text()
        # 查询明细,返回结果
        sql = "SELECT C.PRICE,A.CLINIC_TYPE,A.CLINIC_LABEL,B.DEPT_NAME,A.SHBLX,A.CLINIC_POSITION " \
                "FROM CLINIC_INDEX A,DEPT_DICT B, " \
                "(SELECT A.CLINIC_TYPE,SUM(B.PRICE) AS PRICE FROM CLINIC_TYPE_SETTING A,CURRENT_PRICE_LIST B  " \
                "WHERE A.PRICE_ITEM=B.ITEM_CODE  GROUP BY A.CLINIC_TYPE) C " \
                "WHERE  A.CLINIC_DEPT=B.DEPT_CODE AND A.CLINIC_TYPE=C.CLINIC_TYPE " \
                "AND A.CLINIC_DEPT LIKE '01%' " \
                "AND A.CLINIC_LABEL LIKE '%{cliniclabel}%' " \
                "ORDER BY A.CLINIC_LABEL".format(cliniclabel=cliniclabel)
        Dbconnect.cursor.execute(sql)
        sql_result = Dbconnect.cursor.fetchall()

        # 创建QStandardItemModel实例
        model = QStandardItemModel()
        # 设置此模型的列标题
        model.setHorizontalHeaderLabels(['价格', '挂号等级', '号别', '科室', '号别类型', '楼层'])
        # 填充单元格数据
        row = len(sql_result)
        column = model.columnCount()
        for i in range(row):
            for j in range(column):
                item = QStandardItem(str(sql_result[i][j]))
                model.setItem(i, j, item)
        self.tableView.setModel(model)
        # 框体不可编辑
        self.tableView.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
        self.tableView.show()

    #点击修改按钮,想实现的modify函数,tableview的【价格price】变化,【挂号等级type】同步更新并传入ComboBox
    def cliprice_modify(self):      
        # 定位到【价格】列
        self.tableView.selectColumn(0)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectColumns)
        # 设置QTableView单列可编辑
        #第0列price可编辑
        delegate = self.tableView.setEditTriggers(QAbstractItemView.EditTrigger.DoubleClicked)
        self.tableView.setItemDelegateForColumn(0, delegate)
        #第1列type可编辑
        delegate2 = ComboBoxDelegate(self.tableView)
        self.tableView.setItemDelegateForColumn(0, delegate2)
        # 信号槽连接
        model.dataChanged.connect(self.onDataChanged)


第一次请人帮忙,价格暂定50-100左右,如果可以发咸鱼,我去拍。价格不对也请指正
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-7-7 10:45:02 | 显示全部楼层
首先,关于您的问题,这里并不是一个发布悬赏帖的平台。但是,我会尽力帮助您解决问题。

根据您的代码和需求,我对您的代码进行了修改。以下是修改后的代码:
# 省略了其他没有改动的部分# 重写ComboBox委托class ComboBoxDelegate(QStyledItemDelegate):    def __init__(self, parent=None):        super(ComboBoxDelegate, self).__init__(parent)    def createEditor(self, parent, option, index):        editor = QComboBox(parent)        return editor    def setEditorData(self, editor, index):        price = index.model().data(index, Qt.ItemDataRole.DisplayRole)        sqlprice = "SELECT C.CLINIC_TYPE FROM  (SELECT A.CLINIC_TYPE,SUM(B.PRICE) AS PRICE " \                   "FROM CLINIC_TYPE_SETTING A,CURRENT_PRICE_LIST B  " \                   "WHERE A.PRICE_ITEM=B.ITEM_CODE  GROUP BY A.CLINIC_TYPE) C " \                   "WHERE C.PRICE='{price}'".format(price=price)        Dbconnect.cursor.execute(sqlprice)        sqlprice_result = Dbconnect.cursor.fetchall()        for i in sqlprice_result:            editor.addItem(str(i))        editor.setCurrentIndex(editor.findText(price))    def setModelData(self, editor, model, index):        value = editor.currentText()        model.setData(index, value, Qt.EditRole)    def onDataChanged(self, index):        pass# 省略了其他没有改动的部分# 点击修改按钮,想实现的modify函数,tableview的【价格price】变化,【挂号等级type】同步更新并传入ComboBoxdef cliprice_modify(self):    self.tableView.selectColumn(0)    self.tableView.setSelectionBehavior(QAbstractItemView.SelectColumns)    delegate = QStyledItemDelegate()    self.tableView.setItemDelegateForColumn(0, delegate)    delegate2 = ComboBoxDelegate(self.tableView)    self.tableView.setItemDelegateForColumn(1, delegate2)    self.tableView.model().dataChanged.connect(self.onDataChanged)# 省略了其他没有改动的部分
主要的修改:

1. 在  cliprice_modify  函数中,我改了您设置  delegate  和  delegate2  的方式。这样,第 0 列和第 1 列可以分别使用不同的委托。
2. 我删除了设置编辑触发器 ( setEditTriggers ) 的语句,因为您已经通过委托来控制编辑行为。

希望这些修改能帮助您完成您的需求。如果您还有其他问题,请随时提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-7 10:58:16 | 显示全部楼层
2#说法错误

新鱼油不可以发悬赏帖,理论上可以发,但只能设置鱼币悬赏

根据你提供的代码,我看到你已经完成了大部分工作。在`ComboBoxDelegate`类中,你可以添加一个新的方法来处理数据变化的信号槽连接。

首先,你需要导入`QtCore`模块:
from PySide6.QtCore import Qt, QObject, Signal
然后,在`ComboBoxDelegate`类中,添加如下方法:
class ComboBoxDelegate(QStyledItemDelegate):
    # ...

    def onDataChanged(self, index):
        # 获取编辑器的数据
        editor = self.sender()
        value = editor.currentText()

        # 获取当前行的价格值
        price_index = index.sibling(index.row(), 0)
        price = price_index.data(Qt.DisplayRole)

        # 进行价格匹配查询
        sqlprice = "SELECT C.CLINIC_TYPE FROM (SELECT A.CLINIC_TYPE, SUM(B.PRICE) AS PRICE " \
                   "FROM CLINIC_TYPE_SETTING A, CURRENT_PRICE_LIST B  " \
                   "WHERE A.PRICE_ITEM = B.ITEM_CODE GROUP BY A.CLINIC_TYPE) C " \
                   "WHERE C.PRICE = '{price}'".format(price=price)
        Dbconnect.cursor.execute(sqlprice)
        sqlprice_result = Dbconnect.cursor.fetchall()

        if sqlprice_result:
            # 如果有返回值,则将返回值传给ComboBox
            types = [str(i[0]) for i in sqlprice_result]
            self.setModelData(editor, None, index, types)
        else:
            # 如果没有返回值,则显示提示信息
            QMessageBox.information(None, '提示', '没有价格为{price}的号'.format(price=price))

    def setModelData(self, editor, model, index, types):
        # 清空ComboBox并添加新的选项
        editor.clear()
        editor.addItems(types)

        # 设置当前选中的项
        value = index.model().data(index, Qt.DisplayRole)
        editor.setCurrentIndex(editor.findText(value))

最后,在`CliPriceModifyWindow`类的`cliprice_modify`方法中,连接信号槽:
class CliPriceModifyWindow(CliPriceModifyWindow.Ui_Form, QWidget):
    def __init__(self):
        super(CliPriceModifyWindow, self).__init__()
        self.setupUi(self)
        self.pBtnQuery.clicked.connect(self.cliprice_query)
        self.pBtnModify.clicked.connect(self.cliprice_modify)
        self.pBtnSave.clicked.connect(self.cliprice_save)
        self.pBtnReset.clicked.connect(self.cliprice_reset)

    def cliprice_modify(self):
        # ...

        # 设置QTableView单列可编辑
        delegate = self.tableView.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.tableView.setItemDelegateForColumn(0, delegate)

        # 创建ComboBoxDelegate实例
        delegate2 = ComboBoxDelegate(self.tableView)

        # 设置代理编辑器的信号槽连接
        delegate2.dataChanged.connect(delegate2.onDataChanged)

        # 设置第1列的代理编辑器
        self.tableView.setItemDelegateForColumn(1, delegate2)

这样,当用户双击价格单元格时,会触发`ComboBoxDelegate`中的`onDataChanged`方法,根据价格匹配结果更新ComboBox的选项。如果有返回值,则将返回值传给ComboBox,并将其显示在挂号等级(type)列;如果没有返回值,则显示相应的提示信息。

希望这可以帮助到你,如果有任何进一步的问题,请随时提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-7 11:46:32 | 显示全部楼层
本帖最后由 hejialiangya 于 2023-7-7 11:53 编辑
sfqxx 发表于 2023-7-7 10:58
2#说法错误

新鱼油不可以发悬赏帖,理论上可以发,但只能设置鱼币悬赏


   delegate2.dataChanged.connect(delegate2.onDataChanged)
    ^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'ComboBoxDelegate' object has no attribute 'dataChanged'. Did you mean: 'onDataChanged'?

我.不出dataChanged这个方法


还有一个问题,我从昨天开始就一直想问。
class ComboBoxDelegate(QStyledItemDelegate)
edit不是QComboBox的实例化吗?
为什么里面所有的def,只要是edit.都点不出来,【比如editor.addItem(str(i)),editor.setCurrentIndex(editor.findText(value))】,但是将edit替换成QComboBox就可以正常.出其方法
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-7 11:48:41 | 显示全部楼层
hejialiangya 发表于 2023-7-7 11:46
delegate2.dataChanged.connect(delegate2.onDataChanged)
    ^^^^^^^^^^^^^^^^^^^^^
AttributeErr ...

对不起,我之前犯了一个错误。确实没有`dataChanged`信号,而是应该连接`editor`的`currentTextChanged`信号。请修改`ClipriceModifyWindow`类中的代码如下:
class CliPriceModifyWindow(CliPriceModifyWindow.Ui_Form, QWidget):
    def __init__(self):
        super(CliPriceModifyWindow, self).__init__()
        self.setupUi(self)
        self.pBtnQuery.clicked.connect(self.cliprice_query)
        self.pBtnModify.clicked.connect(self.cliprice_modify)
        self.pBtnSave.clicked.connect(self.cliprice_save)
        self.pBtnReset.clicked.connect(self.cliprice_reset)

    def cliprice_modify(self):
        # ...

        # 设置QTableView单列可编辑
        delegate = self.tableView.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.tableView.setItemDelegateForColumn(0, delegate)

        # 创建ComboBoxDelegate实例
        delegate2 = ComboBoxDelegate(self.tableView)

        # 连接代理编辑器的信号槽
        editor = delegate2.createEditor(None, None, None)
        if isinstance(editor, QComboBox):
            editor.currentTextChanged.connect(delegate2.onDataChanged)

        # 设置第1列的代理编辑器
        self.tableView.setItemDelegateForColumn(1, delegate2)

这样,当用户选择ComboBox中的项时,会触发`ComboBoxDelegate`中的`onDataChanged`方法。

非常抱歉给你带来困扰,请试试这个修改后的代码看是否可以正常工作。如果还有其他问题,请随时提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-7 11:52:51 | 显示全部楼层
sfqxx 发表于 2023-7-7 11:48
对不起,我之前犯了一个错误。确实没有`dataChanged`信号,而是应该连接`editor`的`currentTextChanged` ...

......
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-7 12:03:36 From FishC Mobile | 显示全部楼层
Threebody1 发表于 2023-7-7 11:52
......

……
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-7 12:09:29 | 显示全部楼层
本帖最后由 hejialiangya 于 2023-7-7 13:57 编辑
sfqxx 发表于 2023-7-7 11:48
对不起,我之前犯了一个错误。确实没有`dataChanged`信号,而是应该连接`editor`的`currentTextChanged` ...



调试时断点不触发onDataChanged的事件,
调试会提示:TypeError: ComboBoxDelegate.setModelData() missing 1 required positional argument: 'types'

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-7 14:15:58 | 显示全部楼层
hejialiangya 发表于 2023-7-7 12:09
调试时断点不触发onDataChanged的事件,
调试会提示:TypeError: ComboBoxDelegate.setModelData()  ...

非常抱歉,我之前的代码有误。在`ComboBoxDelegate`类中,`setModelData`方法确实缺少一个必需的参数`types`,我会为你修复这个问题。

请将`ComboBoxDelegate`类的代码修改如下:
class ComboBoxDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super(ComboBoxDelegate, self).__init__(parent)
        self.types = []

    def createEditor(self, parent, option, index):
        editor = QComboBox(parent)
        editor.currentTextChanged.connect(self.onDataChanged)
        return editor

    def setEditorData(self, editor, index):
        value = index.model().data(index, Qt.DisplayRole)
        editor.setCurrentText(value)

    def setModelData(self, editor, model, index):
        value = editor.currentText()
        if value not in self.types:
            QMessageBox.information(None, '提示', '没有价格为{value}的诊所类型'.format(value=value))
            return
        super(ComboBoxDelegate, self).setModelData(editor, model, index)

    def setTypes(self, types):
        self.types = types

    def onDataChanged(self, text):
        editor = self.sender()
        self.commitData.emit(editor)

然后,在`cliprice_modify`方法中,将设置代理编辑器的代码修改如下:
def cliprice_modify(self):
    # ...

    # 创建ComboBoxDelegate实例
    delegate2 = ComboBoxDelegate(self.tableView)

    # 设置第1列的代理编辑器
    self.tableView.setItemDelegateForColumn(1, delegate2)

    # 获取当前行的价格值
    price_idx = self.tableView.model().index(row, 0)
    price = price_idx.data(Qt.DisplayRole)

    # 进行价格匹配查询
    sqlprice = "SELECT C.CLINIC_TYPE FROM (SELECT A.CLINIC_TYPE, SUM(B.PRICE) AS PRICE " \
               "FROM CLINIC_TYPE_SETTING A, CURRENT_PRICE_LIST B " \
               "WHERE A.PRICE_ITEM = B.ITEM_CODE GROUP BY A.CLINIC_TYPE) C " \
               "WHERE C.PRICE = '{price}'".format(price=price)
    Dbconnect.cursor.execute(sqlprice)
    sqlprice_result = Dbconnect.cursor.fetchall()

    if sqlprice_result:
        # 如果有返回值,则将返回值传给ComboBox
        types = [str(i[0]) for i in sqlprice_result]
        delegate2.setTypes(types)
    else:
        # 如果没有返回值,则显示提示信息
        QMessageBox.information(None, '提示', '没有价格为{price}的号'.format(price=price))

这样,当进入编辑状态并选择其他诊所类型时,会触发`ComboBoxDelegate`中的`onDataChanged`方法。

非常抱歉之前给你带来的困惑,请尝试这个更新后的代码,并再次进行调试。如果还有任何问题,请随时告诉我。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-13 22:17

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表