使用uic.loadUI()

时间:2019-03-18 11:44:02

标签: python python-3.x pyqt5 subclass qwidget

从几周以来,我实际上正在使用PyQt5和QtDesigner开发一个小型软件。我已经看了很多tuto,并在SO上寻找了很多答案,但是找不到关于使用uic.loadUI()覆盖QWidget方法的方法的一个。

请注意,我已尽可能简化测试代码以准确指出问题所在:

1 /这不起作用,它正确加载了我的file.ui,但是单击后却无济于事:

import sys
from PyQt5 import uic
from PyQt5.QtWidgets import QApplication, QWidget

class Window(QWidget):
    def __init__(self):
        super().__init__() # Or QWidget.__init__(self)
        self.dlg = uic.loadUi("file.ui")
        self.dlg.show()

    def mousePressEvent(self, event):
        print("click !")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Window()
    app.exec_()

2 /但我发现实际上是这样的:

class Window(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.setWindowTitle("My window")
        self.show()

    def mousePressEvent(self, event):
        print("click !")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Window()
    app.exec_()

据我所知,这似乎是因为我无法覆盖事件的方法。由于mousePressEvent不是QWidget子类self.dlg附带的方法。

现在我知道为什么了,我想知道如何重写mousePressEvent方法并使用它。我想知道重写后的方法是“加载”该方法,还是调用QWidget方法重新定义它,或者只是创建自己的方法来捕获任何事件,但我尝试的所有方法都完全失败了。

无论如何,在此先感谢您的回答/提示/祈祷。

2 个答案:

答案 0 :(得分:2)

假设在创建file.ui时,您正在使用Widget模板:

enter image description here

然后解决方法如下:

import sys
from PyQt5 import uic
from PyQt5.QtWidgets import QApplication, QWidget

class Window(QWidget):
    def __init__(self):
        super().__init__()
        uic.loadUi("file.ui", self)
        self.show()

    def mousePressEvent(self, event):
        print("click !")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Window()
    app.exec_()

为什么在使用时不起作用 self.dlg = uic.loadUi("file.ui") ?因为正如您指出的那样,创建的小部件is self.dlg仍然是从未显示过的赢得窗口,对于uic.loadUi("file.ui", self),您要指出它不会创建窗口,而是会填充现有窗口

更新:

根据您得到的错误:

TypeError: ('Wrong base class of toplevel widget', (<class '__main__.Window'>, 'QMainWindow'))

它允许我推断您没有使用QWidget作为基础,而是使用QMainWindow,因此Window必须继承自QMainWindow:

import sys
from PyQt5 import uic
from PyQt5.QtWidgets import QApplication, QMainWindow

class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        uic.loadUi("file.ui", self)
        self.show()

    def mousePressEvent(self, event):
        print("click !")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Window()
    app.exec_()

答案 1 :(得分:0)

我的方法是在Qt Designer对象检查器中使用 function load(data) { // V4 general update pattern (using merge) // -- FIRST LEVEL OF LIST ITEMS // data join (root is an UL element) var lev1 = d3.select('#root').selectAll('li.lev1') .data(data) // enter: var lev1_enter = lev1.enter() .append('li') .attr('class', 'lev1'); // exit lev1.exit() .remove(); // merge enter selection into update selection so // we can update all new and existing elements lev1 = lev1.merge(lev1_enter) .text(function(d) {return d.id;}); // -- 2ND (NESTED) LEVEL OF LIST ITENS // data join: lev2_update = lev1.selectAll('li.lev2') .data(function(d,i) { return d.values; }) // enter: // HELP: How do I add a single UL element here? // If I call `append('ul')`, I will have mulitple UL, // rather than a signle UL with mulitple LI children. lev2_enter = lev2_update.enter() //.append('ul') <-- This will create a UL for every LI... .append('li') .attr('class', 'lev2'); lev2_update.exit() .remove(); lev2_update.merge(lev2_enter) .text(function(d, i) { return '[' + i + '] ' + d; }) } var data = [ {'id': 'row1', 'values': [0,1,2]}, {'id': 'row2', 'values': [3,4,5]}, {'id': 'row3', 'values': [6,7,8]}, ]; load(data); 上下文菜单项。

这使您可以在设计器中指定特定的窗口小部件应使用要在图形生成器中推送的子类。 getChildFragmentManager()将遵守此规定。

假设您在getSupportFragmentManager()中有一个Promote to...。您可以放置​​uic.loadUi,然后选择MyGraphicsView并输入以下内容:

  • 基类名称:(预填到my_graphics_view.py
  • 提升的班级名称:QGraphicsView
  • 头文件:Promote to...QGraphicsView会为您调整扩展名)

...然后单击“添加”,然后单击“升级”,就完成了。

我只注意到了两个警告:

  1. 据我所知,使用MyGraphicsView时没有my_graphics_view.h方法,而loadUi在构建子窗口小部件树之前返回,因此如果要在setupUi之后运行任何自定义代码,您必须将其放入具有诸如uic.loadUi之类名称的方法中,并在调用__init__之后自行调用它。

  2. 由于我不知道的原因,我从Kubuntu Linux 16.04 LTS使用的Qt Designer 5.5.1的副本在“促进”对话框的已知小部件下拉菜单中没有提供__init__

    但是,如果您编辑widget.configure_children()文件,则Qt Designer和widget = uic.loadUi(...)都不会有问题。看起来确实是这样...下拉小部件中的一个神秘遗漏,仅此而已。

原始QMainWindow文件中的内容如下:

.ui

请注意,根据this page,相当于loadUi的PySide2将父级作为第二个参数而不是自定义子类,因此您基本上被迫使用此方法在PySide2下。