Qt Designer推出了小部件布局

时间:2016-03-18 23:06:48

标签: python layout pyqt qt-designer

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

enter image description here

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

我上面尝试创建了类型为widget的seprate ui文件,但是当我从我的MainWindow中提升它时,它将不会显示,而pyuic生成的代码会将它添加到布局中,但它不会呈现在主窗口。

enter image description here

在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))

2 个答案:

答案 0 :(得分:1)

推荐的小部件只是标准Qt小部件的占位符。您无法以这种方式为Qt Designer创建自定义窗口小部件。

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

修改

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

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模块,这样你就可以再次回到干净的未经编辑的文件。

答案 1 :(得分:0)

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

我不知道自定义窗口小部件的顶级窗口小部件是什么,但最好是Qt设计器中QWidget列表中的QFrameContainers并在其中添加子窗口小部件,让我们将此自定义窗口小部件文件命名为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,请进行必要的更改。此代码未经过测试,因此如果找到,也必须解决语法错误。