【问题标题】:Updating a Qtablewidget from contextmenu linedit-pyqt从上下文菜单 qlineedit-pyqt 更新 Qtablewidget
【发布时间】:2012-08-14 19:38:18
【问题描述】:

我有一个QTableWidget,我想用它从嵌入到上下文菜单中的QLinEdit 更新。现在,在QLinEdit 中输入一个服务器名称,当按下该键时,程序会扫描 MySQL 数据库以查看服务器名称是否在其中,如果是,则使用来自服务器名称的数据更新QTableWidget表,如果找不到,它会给出错误messageBox

我不能做的是连接上下文菜单QLinEdit 来更新QTableWidget

QTableWidget 连接到上下文菜单:

self.table1.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.table1.customContextMenuRequested.connect(self.handleHeaderMenu)

上下文菜单:

    def handleHeaderMenu(self, pos):
        self.custom_choice = QtGui.QLineEdit()
        self.menu = QtGui.QMenu()
        self.custom_choice.setPlaceholderText("Server")
        self.wac = QtGui.QWidgetAction(self.menu)
        self.wac.setDefaultWidget(self.custom_choice)
        self.menu.setStyleSheet("QMenu::item {background-color: #264F7D;color: white; font-weight:bold;}")
        self.menu.addAction("Choose Server to Monitor:")
        self.menu.addSeparator()
        self.actionJuliet = self.menu.addAction('Juliet')
        self.actionJulietleft = self.menu.addAction('JulietLeft')
        self.actionPong = self.menu.addAction('Pong')
        self.actionHulk = self.menu.addAction('Hulk')
        self.actionCustom = self.menu.addAction(self.wac)
        action = self.menu.exec_(QtGui.QCursor.pos())
        self.connect(self.custom_choice, QtCore.SIGNAL("returnPressed()"),self.refreshdata)

数据获取器/扫描器:

def get_data(self):
    self.tx = self.custom_choice.text()
    self.model.execute("show TABLES;")
    table_array = []
    table_names = self.model.fetchall()
    for lines in table_names:
        lines = str(lines)
        lines = lines.strip("()""''"",")
        table_array.append(lines)
    if any("%s" % self.tx in s for s in table_array):
        table_name = self.tx
        self.model.execute("""SELECT computer_name 
                              FROM %s""" % (table_name))
        new_user_name = self.model.fetchall()
        print new_user_name,table_name
        self.model.execute("""SELECT idle_time 
                              FROM %s""" % (table_name))
        new_idle = self.model.fetchall()
        self.model.execute("""SELECT files_opened 
                              FROM %s""" % (table_name))
        new_files = self.model.fetchall()
        self.model.execute("""SELECT active_time 
                              FROM %s""" % (table_name))
        new_active = self.model.fetchall()
        self.model.execute("""SELECT session_type 
                           FROM %s""" % (table_name))
        new_session = self.model.fetchall()
        self.model.execute("""SELECT cpu 
                           FROM %s""" % (table_name))
        new_cpu_load = self.model.fetchall()
        self.model.execute("""SELECT avg_disk_queue 
                           FROM %s""" % (table_name))
        new_disk_queue_load = self.model.fetchall()
        new_data_user = [item0[0] for item0 in new_user_name]
        new_data_idle = [item1[0] for item1 in new_idle]
        new_data_files = [item2[0] for item2 in new_files]
        new_data_active = [item3[0] for item3 in new_active]
        new_data_session = [item4[0] for item4 in new_session]
        new_data_cpu_load = [item5[0] for item5 in new_cpu_load]
        new_data_disk_queue_load = [item6[0] for item6 in new_disk_queue_load]
        self.lista = new_data_user
        self.listb = new_data_disk_queue_load
        self.listc = new_data_cpu_load
        self.listd = new_data_active
        self.liste = new_data_files
        self.listf = new_data_session
        self.listg = new_data_idle  
        self.mystruct2 = {'A':self.lista, 'B':self.listb, 'C':self.listc,'E':self.liste,'D':self.listd,'F':self.listf,'G':self.listg} 

【问题讨论】:

    标签: python pyqt qtablewidget


    【解决方案1】:

    handleHeaderMenu 的设计有点偏离。当前结构方式的主要问题之一是您将信号连接到QLineEdit 弹出菜单已经完成之后。所以你会错过那个信号。

    action = self.menu.exec_(QtGui.QCursor.pos())
    self.connect(self.custom_choice, 
                    QtCore.SIGNAL("returnPressed()"),
                    self.refreshdata)
    

    QMenu.exec_() 是一个阻塞调用。它启动菜单的事件循环并等待它完成。一旦它关闭并返回所选的 QAction,您就可以建立连接。在我的下一点之后,我将对此进行更正......

    您每次从头开始构建的菜单不必保存到成员属性并在外部使用。有两种方法可以进行自定义弹出菜单。如果它主要是静态的,那么您可以在您的类 init 中构建它一次,或者使其成为自己的类,然后重用该实例。或者在你的情况下,你可以每次都建立它,这很好。但是,与其依赖对菜单组件的持久引用并使用信号,为什么不只是临时构建它并显式处理结果呢?

    def handleHeaderMenu(self, pos):
        menu = QtGui.QMenu()
        menu.setStyleSheet("""
            QMenu::item {
                background-color: #264F7D;
                color: white; 
                font-weight:bold;}
        """)
        text = menu.addAction("Choose Server to Monitor:")
        text.setEnabled(False)
        menu.addSeparator()
    
        actionJuliet = menu.addAction('Juliet')
        actionJulietleft = menu.addAction('JulietLeft')
        actionPong = menu.addAction('Pong')
        actionHulk = menu.addAction('Hulk')
    
        wac = QtGui.QWidgetAction(menu)
        custom_choice = QtGui.QLineEdit()
        custom_choice.setPlaceholderText("Server")
        wac.setDefaultWidget(custom_choice)
        menu.addAction(wac)
    
        menu.setActiveAction(wac)
        custom_choice.returnPressed.connect(wac.trigger)
    
        action = menu.exec_(QtGui.QCursor.pos())
        if action:
            if action == wac:
                self.tx = str(custom_choice.text()).strip()
            else:
                self.tx = str(action.text())
    
            self.refreshdata()
    
    def refreshdata(self):
        print self.tx
    

    这里我们只是为菜单创建了一堆临时小部件,这些小部件将被垃圾收集。显示菜单后,我们检查返回的操作,然后手动设置我们的表格属性,并调用刷新。此外,我们需要设置来自自定义 QLineEdit 的信号以在内部触发其小部件操作。

    最后,每次你想加载这些数据时,真的有必要进行 8 次 sql 查询和一大堆数据重组吗?这可以高度简化:

    def get_data(self):
    
        table_check = """
            SELECT table_name FROM information_schema.tables 
            WHERE table_schema = %s AND table_name = %s 
            """
    
        table_name = self.tx
        count = self.model.execute(table_check, (self.theDatabaseName, table_name))
        if not count:
            # warn the user that the table name does not exist
            warn_user_of_bad_table()
            return
    
        sql = """
            SELECT 
                computer_name, idle_time, files_opened, 
                active_time, session_type, cpu, avg_disk_queue
            FROM %s 
            """ % table_name
    
        count = self.model.execute(sql)
        if not count:
            warn_database_error()
            return
    
        results = self.model.fetchall()
        user, idle , files, active, session, cpu, disk = zip(*results)
        self.lista = user
        self.listb = disk
        self.listc = cpu
        self.listd = active
        self.liste = files
        self.listf = session
        self.listg = idle  
        self.mystruct2 = {
            'A' : self.lista, 
            'B' : self.listb, 
            'C' : self.listc,
            'E' : self.liste,
            'D' : self.listd,
            'F' : self.listf,
            'G' : self.listg
        }
    

    这里只需要两个查询。第一个非常简单的检查表是否存在,通过使用方案,而不是通过大的 SHOW TABLES 输出进行解析。第二个是在一个查询中获取所有数据(作为一堆行,然后使用zip 将它们重新组合成列。

    【讨论】:

    • 但是我如何更新实际表,如果我将它作为初始数据传递给 tablewidget,initialdata 引用在这些函数中的任何一个之前,所以它给了我一个错误,说没有这样变量是否与 handleheadermenu 中定义的变量一样?
    • 我不确定我是否理解您的问题。您不需要从该弹出菜单访问任何内容。它应该做的就是将选择的值保存到self.tx,然后调用你的刷新方法。然后刷新方法会查看该值并执行您的 sql 查询,然后可以更新您的表。
    • 是的,但是如何将字典 mystruct2 传递给表本身?
    • 我只是假设你的可调用对象是你想要的实际代码的顺序。如果不应该先调用 refresh,则让弹出窗口调用 getdata,然后调用 refresh
    • 我目前已设置,但弹出窗口在 init 函数中,这就是它给我错误的原因。
    猜你喜欢
    • 2017-08-29
    • 1970-01-01
    • 2010-10-21
    • 2012-08-08
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多