【问题标题】:How can I inherit QTableWidget and my class MainWindow?如何继承 QTableWidget 和我的类 MainWindow?
【发布时间】:2017-07-21 16:31:57
【问题描述】:

首先,我对 python 比较陌生,对 PyQt 也很陌生。我正在向面向对象编程迈出第一步,我一直在查看在线教程,但我遇到了多重继承问题。

我有一个名为 CreateTable() 的类,其目的是在我的应用程序窗口中创建一个 QTableWidget,当单击一行时,它会打开一个上下文菜单,然后您可以选择选项来绘制所选行的图形。其中图形选项连接到另一个类 Plotter()。

我的问题是 CreateTable 需要从 PyQt 和我的类 MainWindow 继承 QTableWidget,因为我需要引用布局变量才能将我的图形嵌入到我的应用程序窗口中。

我尝试继承的代码如下,大量借鉴了这里:How does Python's super() work with multiple inheritance?

class QTable(QTableWidget):
  def __init__(self):
    super(QTable, self).__init__()
class PassMain(MainWindow):
  def __init__(self):
    super(PassMain, self).__init__()
class PassMainTable(PassMain, QTable):
  def __init__(self):
    super(PassMainTable, self).__init__()

主要问题是当我尝试将图表放在我的 MainWindow 布局中时。

self.vboxRight.addWidget(self.Graph) 

这是我创建表格和调用绘图仪的代码

class CreateTable(PassMainTable): #QTableWidget
def __init__(self, Data, row, col, colHeaders, rowHeaders): #Index, ColumnHeaders
    super(CreateTable, self).__init__()


    self.setSelectionBehavior(self.SelectRows)

    print("Start initialization")
    self.ColHeader = colHeaders
    self.setRowCount(row)
    self.setColumnCount(col)
    self.data = Data
    self.setHorizontalHeaderLabels(colHeaders)

    print("Right before for loop")

    n = len(Data)
    m = len(colHeaders)

    for i in range(n):
        DataValues = self.data.iloc[i,:]
        print("values are {}".format(DataValues))
        #m = len(values)
        ConvertedVals = pd.to_numeric(DataValues)

        ValList = DataValues.values.tolist()
        print(ValList)

        for j in range(0,m):
            self.item = QTableWidgetItem(str(round(ValList[j],5)))
            #print("{}, {}".format(i, j))
            self.setItem(i,j, self.item)

def contextMenuEvent(self, event):

    menu = QMenu(self)
    graphAction = menu.addAction("Graph")
    compareAction = menu.addAction("Compare")
    scatterAction = menu.addAction("Plot types")
    aboutAction = menu.addAction("about")
    quitAction = menu.addAction("quit")
    printAction = menu.addAction("Print Row")
    action = menu.exec_(self.mapToGlobal(event.pos()))
    if action == quitAction:
        qApp.quit()
    elif action == printAction:
        self.selected = self.selectedItems()
        n = len(self.selected)
        print("n is {}".format(n))
        for i in range(n):
            self.selected[i] = str(self.selected[i].text())
        for i in range(n):
            self.selected[i] = float(self.selected[i])
        print(self.selected)
    elif action == graphAction:
        self.selected = self.selectedItems()
        n = len(self.selected)
        for i in range(n):
            self.selected[i] = str(self.selected[i].text())
        for i in range(n):
            self.selected[i] = float(self.selected[i])
        print("right before plotter called")

        self.Graph = Plotter(self.selected, self.ColHeader)

        self.vboxRight.addWidget(self.Graph)
    else:
        print("u clicked something other than quit")

更糟糕的是,PyQt 将我所有的错误都作为异常捕获,所以我得到的所有错误都是“进程以退出代码 1 完成”

如果您需要进一步参考我的完整代码,我在这里提供了一个链接:https://github.com/Silvuurleaf/Data-Analysis-and-Visualization-GUI/blob/master/Plotter3.1.py

谢谢大家能给我的任何帮助。

【问题讨论】:

  • 我不明白为什么要一次继承QTableWidget和QMainWindow,这样不合适,都继承自QWidget。
  • 添加widget不等于继承
  • 您可以提供 .csv 文件。另一件事,菜单应该能够在窗口中的任何地方运行,如果是这样,我认为当菜单在 QTableWidget 之外运行时应该禁用 QAction 图。
  • 我不想从 QMainWindow 继承。我创建了一个名为 MainWindow 的单独类,在其中定义了布局 vboxRight,这是我想要嵌入图表的地方。
  • 另外,我希望上下文菜单仅在单击数据表时可用,这就是我在 CreateTable 类中定义上下文菜单方法的原因。

标签: python pyqt pyqt5 multiple-inheritance


【解决方案1】:

为了共享数据,不必从小部件继承,只需使用信号,这是 PyQt 中异步共享数据的自然方式。例如,在您的情况下,我们将创建一个名为 dataSignal 的信号,根据您要使用变量 self.selectedself.ColHeader 的代码,第一个是 list 类型,第二个numpy.ndarray 这样我们就可以构建信号了:

class CreateTable(QTableWidget): #QTableWidget
    dataSignal = pyqtSignal(list, np.ndarray)
    def __init__(self, Data, row, col, colHeaders, rowHeaders): #Index, ColumnHeaders
        super(CreateTable, self).__init__()


        self.setSelectionBehavior(self.SelectRows)

        print("Start initialization")
        self.ColHeader = colHeaders
        self.setRowCount(row)
        self.setColumnCount(col)
        self.data = Data
        self.setHorizontalHeaderLabels(colHeaders)

        print("Right before for loop")

        n = len(Data)
        m = len(colHeaders)

        for i in range(n):
            DataValues = self.data.iloc[i,:]
            print("values are {}".format(DataValues))
            #m = len(values)
            ConvertedVals = pd.to_numeric(DataValues)

            ValList = DataValues.values.tolist()
            print(ValList)

            for j in range(0,m):
                self.item = QTableWidgetItem(str(round(ValList[j],5)))
                #print("{}, {}".format(i, j))
                self.setItem(i,j, self.item)

    def contextMenuEvent(self, event):

        menu = QMenu(self)
        graphAction = menu.addAction("Graph")
        compareAction = menu.addAction("Compare")
        scatterAction = menu.addAction("Plot types")
        aboutAction = menu.addAction("about")
        quitAction = menu.addAction("quit")
        printAction = menu.addAction("Print Row")
        action = menu.exec_(self.mapToGlobal(event.pos()))
        if action == quitAction:
            qApp.quit()
        elif action == printAction:
            self.selected = self.selectedItems()
            n = len(self.selected)
            print("n is {}".format(n))
            for i in range(n):
                self.selected[i] = str(self.selected[i].text())
            for i in range(n):
                self.selected[i] = float(self.selected[i])
            print(self.selected)
        elif action == graphAction:
            self.selected = self.selectedItems()
            n = len(self.selected)
            for i in range(n):
                self.selected[i] = str(self.selected[i].text())
            for i in range(n):
                self.selected[i] = float(self.selected[i])
            print("right before plotter called")

            print(type(self.selected), type(self.ColHeader))
            self.dataSignal.emit(self.selected, self.ColHeader)

        else:
            print("u clicked something other than quit")

然后在 MainWindow 类中创建一个插槽,在此创建 Plotter 对象并将其添加到布局中。

def dataPlotter(self, x_data,y_data):
    self.Graph = Plotter(x_data, y_data)
    self.vboxRightBottom.addWidget(self.Graph)

为此,我们在创建CreateTable 对象时连接信号:

self.Table = CreateTable(self.BaseStats, row, col, colHeaders, rowHeaders)
self.Table.dataSignal.connect(self.dataPlotter)
self.vboxRightBottom.addWidget(self.Table)

完整代码为here

【讨论】:

  • 是的,效果很好!!我必须调整页面的布局,并且可能会使用您更新我当前绘图的想法,因为它会将图表放在我的数据表下方,否则非常感谢!
猜你喜欢
  • 1970-01-01
  • 2017-02-24
  • 1970-01-01
  • 1970-01-01
  • 2016-01-17
  • 1970-01-01
  • 2023-03-10
  • 2018-03-10
  • 1970-01-01
相关资源
最近更新 更多