【问题标题】:Qt Designer promoted widget layoutQt Designer 提升了小部件布局
【发布时间】:2016-07-05 21:03:00
【问题描述】:

我正在使用 Qt Designer 来设计我的用户界面,并且我想构建自定义小部件,这些小部件可以是现有 qt 小部件的组合,例如 QLabel 和 QPushButton 附加屏幕截图

。

现在我希望它独立于它自己的业务逻辑、信号和插槽在一个单独的 python 文件中,但希望将它作为一个组件添加到我的主屏幕。

我在上面尝试通过创建单独的小部件类型的 ui 文件,但是当我从我的 MainWindow 提升它时,它不会显示出来,并且 pyuic 生成的代码会将它添加到布局中,但它没有呈现在主窗口。

有没有办法在 PyQt 和 QDesigner 中做到这一点?

编辑:

下面是实际代码:

timer.py:

from PyQt4 import QtGui, QtCore
from datetime import timedelta, datetime

from logbook import info


import timer_ui


class Timer(QtGui.QWidget, timer_ui.Ui_TimerWidget):

    start_time = None
    running = False
    total_time = 0
    time_spent = ''

    activity = None

    stopwatch = 0
    elapsed_time = None
    total_elapsed_time = timedelta()

    def __init__(self, parent=None):
        super(self.__class__, self).__init__(parent)

        self.setupUi(parent) #for custom widget parent is main window here which is dashboard

        self.lcdNumber.setDigitCount(12)

        self.qt_timer = QtCore.QTimer(self)
        self.qt_timer.timeout.connect(self.timer_event)
        self.qt_timer.start(1000)

        self.goButton.clicked.connect(self.go)
        self.breakButton.clicked.connect(self.break_timer)

    def go(self):
        # date text format .strftime('%a, %d %b %Y %H:%M:%S')
        self.start_time = datetime.now().replace(microsecond=0)
        self.running = True




        self.goButton.setEnabled(False)
        self.breakButton.setEnabled(True)

    def break_timer(self):
        ''' break finishes the activity '''
        break_time = datetime.now().replace(microsecond=0)
        self.activity.log_break(break_time.isoformat())
        self.activity = None  # activity completed

        self.total_elapsed_time += self.elapsed_time
        info(self.total_elapsed_time)

        self.running = False


        # self.lcdNumber.display(str(self.timer.get_elapsed()))

        self.goButton.setEnabled(True)
        self.breakButton.setEnabled(False)


    def timer_event(self):
        '''Updates the widget every second'''

        if self.running == True:
            current_time = datetime.now().replace(microsecond=0)

            # if self.elapsed_time is None:

            self.elapsed_time = current_time - self.start_time
            # else:
            #self.elapsed_time += current_time - self.timer.start_time.replace(microsecond=0)
            if self.total_elapsed_time is not None:
                 self.lcdNumber.display(str(self.elapsed_time + self.total_elapsed_time))
            else:
                self.lcdNumber.display(str(self.elapsed_time))

mainwindow.py:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'dashboard.ui'
#
# Created: Sat Mar 19 11:40:35 2016
#      by: PyQt4 UI code generator 4.10.4
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(772, 421)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.verticalLayout = QtGui.QVBoxLayout()
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.widget = Timer(self.centralwidget)

        self.verticalLayout.addWidget(self.widget)

        self.horizontalLayout = QtGui.QHBoxLayout()

        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.userNameLabel = QtGui.QLabel(self.centralwidget)
        self.userNameLabel.setObjectName(_fromUtf8("userNameLabel"))
        self.horizontalLayout.addWidget(self.userNameLabel)
        self.logoutButton = QtGui.QPushButton(self.centralwidget)
        self.logoutButton.setEnabled(True)
        self.logoutButton.setObjectName(_fromUtf8("logoutButton"))
        self.horizontalLayout.addWidget(self.logoutButton)

        self.verticalLayout.addLayout(self.horizontalLayout)

        self.listView = QtGui.QListView(self.centralwidget)
        self.listView.setObjectName(_fromUtf8("listView"))
        self.verticalLayout.addWidget(self.listView)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)
        self.menuBar = QtGui.QMenuBar(MainWindow)
        self.menuBar.setGeometry(QtCore.QRect(0, 0, 772, 23))
        self.menuBar.setObjectName(_fromUtf8("menuBar"))
        MainWindow.setMenuBar(self.menuBar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "Title", None))
        self.userNameLabel.setText(_translate("MainWindow", "You are now logged in as", None))
        self.logoutButton.setText(_translate("MainWindow", "Logout", None))

from timer import Timer

timer_ui.py:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'timer.ui'
#
# Created: Sat Mar 19 11:41:40 2016
#      by: PyQt4 UI code generator 4.10.4
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_TimerWidget(object):
    def setupUi(self, TimerWidget):
        TimerWidget.setObjectName(_fromUtf8("TimerWidget"))
        TimerWidget.resize(412, 52)
        self.horizontalLayout = QtGui.QHBoxLayout(TimerWidget)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.label = QtGui.QLabel(TimerWidget)
        self.label.setObjectName(_fromUtf8("label"))
        self.horizontalLayout.addWidget(self.label)
        self.lcdNumber = QtGui.QLCDNumber(TimerWidget)
        self.lcdNumber.setAutoFillBackground(False)
        self.lcdNumber.setNumDigits(12)
        self.lcdNumber.setSegmentStyle(QtGui.QLCDNumber.Flat)
        self.lcdNumber.setObjectName(_fromUtf8("lcdNumber"))
        self.horizontalLayout.addWidget(self.lcdNumber)
        self.goButton = QtGui.QPushButton(TimerWidget)
        self.goButton.setObjectName(_fromUtf8("goButton"))
        self.horizontalLayout.addWidget(self.goButton)
        self.breakButton = QtGui.QPushButton(TimerWidget)
        self.breakButton.setObjectName(_fromUtf8("breakButton"))
        self.horizontalLayout.addWidget(self.breakButton)

        self.retranslateUi(TimerWidget)
        #QtCore.QMetaObject.connectSlotsByName(TimerWidget)

    def retranslateUi(self, TimerWidget):
        #TimerWidget.setWindowTitle(_translate("TimerWidget", "Form", None))
        self.label.setText(_translate("TimerWidget", "Total hours spent", None))
        self.goButton.setText(_translate("TimerWidget", "Go!", None))
        self.breakButton.setText(_translate("TimerWidget", "Break", None))

【问题讨论】:

    标签: python layout pyqt qt-designer


    【解决方案1】:

    升级的小部件只是标准 Qt 小部件的占位符。您不能以这种方式为 Qt Designer 创建自定义小部件。

    可以,但过程比简单的小部件推广要复杂得多。请参阅 PyQt 文档中的 Writing Qt Designer Plugins,有关详细教程,请参阅 Python Wiki 上的 Using Python Custom Widgets In Qt Designer。 PyQt source code 还有更多示例(查看examples/designer/plugins)。

    编辑:

    您的代码有两个问题。首先,您在Timer 类中将错误的参数传递给setupUi。你应该这样修复它:

    class Timer(QtGui.QWidget, timer_ui.Ui_TimerWidget):
        ...
        def __init__(self, parent=None):
            super(Timer, self).__init__(parent)
            self.setupUi(self) # pass in self, not parent
    

    其次,您编辑了 mainwindow.py 文件并破坏了其中一个布局。永远,永远编辑pyuic生成的模块!你打破的就是这条线:

            # self.verticalLayout = QtGui.QVBoxLayout()
            self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
    

    但不要尝试通过编辑来解决此问题 - 相反,请确保您重新生成所有带有 pyuic 的 ui 模块,以便您再次回到干净、未编辑的文件。

    【讨论】:

    • 我不想在 qt 设计器中渲染它,而只是推广我现在能够做到的。但是,当我的应用程序与占位符在同一位置编译时,需要呈现由标准小部件组合而成的自定义小部件。
    • @AftabNaveed。那么,您需要发布一些实际代码。来自 Qt Designer 的图像根本无法用于调试。
    • timer_ui 由 QtDesigner pastebin.com/XeDaFjk8 生成,我的 ui 包装在这里 pastebin.com/GwwLTpP9 最后 MainWindow 在这里 pastebin.com/fDK9yiLd MainWindow 是占位符的父级,占位符是 timer.py 环绕QtDesigner 生成的 Widget。效果很好,但我无法正确对齐。
    • @AftabNaveed。我已将代码添加到您的问题中。有关如何修复它,请参阅我的答案的编辑。
    【解决方案2】:

    我一直这样做,即构建自定义小部件并在我的主窗口中使用它们。

    我不知道您的自定义小部件的顶级小部件是什么,但它最好是 Qt 设计器中 Containers 列表中的 QWidget 或 QFrame 并在其中添加子小部件,让我们将此自定义小部件文件命名为 custom.ui。

    接下来,创建一个 Python 类,如下所示:

    Form, Base = uic.loadUiType('/path/to/custom.ui') # this path should be a relative path. For testing you can use absolute path.
    class CustomWidget(Form, Base):
        def __init__(self, parent=None):
            super(CustomWidget, self).__init__(parent)
            self.setupUi(self)
    

    您可以为上述类添加任意数量的自定义逻辑信号和槽。

    类似地为您的主窗口创建一个类,然后在该主类中创建一个 CustomWidget 对象并将该对象添加到布局中。

    Form2, Base2 = uic.loadUiType('/path/to/dashboard.ui') # this path should be a relative path. For testing you can use absolute path.
    class Window(Form2, Base2):
        def __init__(self, parent=None):
            super(Window, self).__init__(parent)
            self.setupUi(self)
            self.cWidget = CustomWidget(self)
            self.layout.addWidget(self.cWidget)
    

    注意:此代码与 Python 2.x 兼容,如果您使用的是 Python 3.x,请进行必要的更改。此代码未经测试,因此如果发现语法错误也必须解决。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-06
      • 2014-12-17
      • 1970-01-01
      相关资源
      最近更新 更多