在 QStackedWidget 对象内定位内部小部件

Posted

技术标签:

【中文标题】在 QStackedWidget 对象内定位内部小部件【英文标题】:Position internal widget inside QStackedWidget object 【发布时间】:2019-03-19 23:01:44 【问题描述】:

我有几个选项卡,在“管理”选项卡内,我想显示两个页面:一个锁定页面(在输入凭据之前)和另一个解锁页面(成功登录后)。为此,我使用QStackedWidget() 在两个页面之间切换。我创建了一个锁定的登录屏幕,但似乎无法将对象移动到页面的中心。

我查看了moving widgets inside QStackedWidget 和centering widgets in the center of the screen,但我的对象似乎没有改变位置。我尝试使用桌面尺寸和父小部件将使用move() 的整个内部小部件移动到屏幕的中心,但无济于事。我怎样才能将登录字段移动到页面的中心?谢谢!

当前:

要求:

代码:

from PyQt4 import QtGui, QtCore
# from load_CSS import load_CSS
# from widgets import UniversalPlotWidget
import sys
import time

def exit_application():
    """Exit program event handler"""

    sys.exit(1)

class VerticalTabBar(QtGui.QTabBar):
    def __init__(self, width, height, parent=None):
        super(VerticalTabBar, self).__init__(parent)
        self.width = width
        self.height = height

    def tabSizeHint(self, index):
        return QtCore.QSize(self.width, self.height)

    def paintEvent(self, event):
        painter = QtGui.QStylePainter(self)
        tab_options = QtGui.QStyleOptionTab()

        for tab in range(self.count()):
            self.initStyleOption(tab_options, tab)
            painter.drawControl(QtGui.QStyle.CE_TabBarTabShape, tab_options)
            painter.save()

            size = tab_options.rect.size()
            size.transpose()
            rectangle = QtCore.QRect(QtCore.QPoint(), size)
            rectangle.moveCenter(tab_options.rect.center())
            tab_options.rect = rectangle

            center = self.tabRect(tab).center()
            painter.translate(center)
            painter.rotate(90)
            painter.translate(-center)
            painter.drawControl(QtGui.QStyle.CE_TabBarTabLabel, tab_options);
            painter.restore()

class TabWidget(QtGui.QTabWidget):
    def __init__(self, *args, **kwargs):
        QtGui.QTabWidget.__init__(self, *args, **kwargs)
        self.setTabBar(VerticalTabBar(kwargs.pop('width'), kwargs.pop('height')))
        self.setTabPosition(QtGui.QTabWidget.West)
        self.setTabShape(QtGui.QTabWidget.Rounded)

class AdminTabWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(AdminTabWidget, self).__init__(parent)
        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.admin_page_locked_init()
        self.admin_page_unlocked_init()

        self.admin_page_layout = QtGui.QGridLayout()

        self.admin_page_switch = QtGui.QStackedWidget()
        self.admin_page_switch.addWidget(self.admin_locked_tab)
        self.admin_page_switch.addWidget(self.admin_unlocked_tab)
        self.admin_page_switch.setCurrentIndex(0)
        self.admin_page_layout.addWidget(self.admin_page_switch,0,0)

    def admin_page_locked_init(self):
        self.admin_locked_tab = QtGui.QWidget()
        self.admin_locked_tab.setFixedSize(550,225)
        self.admin_locked_layout = QtGui.QGridLayout()

        self.username_label = QtGui.QLabel('Username: ')
        self.username_field = QtGui.QLineEdit()
        self.username_field.returnPressed.connect(self.verify_credentials)
        self.space_label = QtGui.QLabel(' ')
        self.space_label.setFixedHeight(25)
        self.password_label = QtGui.QLabel('Password: ')
        self.password_field = QtGui.QLineEdit()
        self.password_field.returnPressed.connect(self.verify_credentials)
        self.password_field.setEchoMode(QtGui.QLineEdit.Password)

        self.verify_button = QtGui.QPushButton('Ok')
        self.verify_button.clicked.connect(self.verify_credentials)
        self.cancel_button = QtGui.QPushButton('Cancel')
        self.cancel_button.clicked.connect(self.unauthorized)

        self.status_label = QtGui.QLabel('')
        self.status_label.setAlignment(QtCore.Qt.AlignCenter)

        self.button_layout = QtGui.QGridLayout()
        self.button_layout.addWidget(self.verify_button,0,0,1,1)
        self.button_layout.addWidget(self.cancel_button,0,1,1,1)

        self.admin_locked_layout.addWidget(self.username_label,0,0,1,1)
        self.admin_locked_layout.addWidget(self.username_field,0,1,1,1)
        self.admin_locked_layout.addWidget(self.space_label,1,0,1,3)
        self.admin_locked_layout.addWidget(self.password_label,2,0,1,1)
        self.admin_locked_layout.addWidget(self.password_field,2,1,1,1)
        self.admin_locked_layout.addWidget(self.status_label,3,0,1,3)
        self.admin_locked_layout.addLayout(self.button_layout,4,0,1,3)

        self.admin_locked_tab.setLayout(self.admin_locked_layout)

    def verify_credentials(self):
        print('button pressed')
        # Grab username/password from input fields
        self.username = str(self.username_field.text())
        self.password = str(self.password_field.text())
        self.status_label.setText('Verifying')
        self.status_label.setStyleSheet('QLabel color: rgb(117,255,161)')
        self.spin(.001)
        print('verified')

    def spin(self, seconds):
        """Pause for set amount of seconds, replaces time.sleep so program doesnt stall"""

        time_end = time.time() + seconds
        while time.time() < time_end:
            QtGui.QApplication.processEvents()

    def unauthorized(self):
        print('unauthorized')
        self.status_label.setText('Invalid username and/or password')
        self.status_label.setStyleSheet('QLabel color: rgb(255,65,106)')

    def admin_page_unlocked_init(self):
        self.admin_unlocked_tab = QtGui.QWidget()
        admin_unlocked_layout = QtGui.QGridLayout()
        admin_unlocked_button = QtGui.QPushButton('unlocked')
        admin_unlocked_layout.addWidget(admin_unlocked_button)
        self.admin_unlocked_tab.setLayout(admin_unlocked_layout)

    def get_admin_page_layout(self):
        return self.admin_page_layout

if __name__ == '__main__':

    # Create main application window
    app = QtGui.QApplication(sys.argv)
    # app.setStyleSheet(load_CSS(1))
    app.setStyle(QtGui.QStyleFactory.create("Cleanlooks"))
    font = QtGui.QFont('Ubuntu', 20)
    font.setWeight(70)
    app.setFont(font)

    screen_height = QtGui.QApplication.desktop().screenGeometry().height()
    main_window_tab = TabWidget(width=300, height=screen_height/8)
    main_window_tab.setWindowTitle("Tab Layout")
    main_window_tab.setWindowFlags(QtCore.Qt.FramelessWindowHint)
    main_window_tab.showMaximized()

    tab1 = QtGui.QWidget()
    tab2 = QtGui.QWidget()
    tab3 = QtGui.QWidget()
    tab4 = QtGui.QWidget()
    tab5 = QtGui.QWidget()
    tab6 = QtGui.QWidget()
    tab7 = QtGui.QWidget()
    admin_tab = QtGui.QWidget()

    admin_tab_widget = AdminTabWidget()
    admin_tab.setLayout(admin_tab_widget.get_admin_page_layout())

    main_window_tab.addTab(admin_tab, "Admin")
    main_window_tab.addTab(tab1, "tab1")
    main_window_tab.addTab(tab2, "tab2")
    main_window_tab.addTab(tab3, "tab3")
    main_window_tab.addTab(tab4, "tab4")
    main_window_tab.addTab(tab5, "tab5")
    main_window_tab.addTab(tab6, "tab6")
    main_window_tab.addTab(tab7, "tab7")

    main_window_tab.show()

    QtGui.QShortcut(QtGui.QKeySequence('Ctrl+Q'), main_window_tab, exit_application)

    sys.exit(app.exec_())

【问题讨论】:

【参考方案1】:

这个想法是在布局中设置QStackedWidgetQt::AlignCenter 对齐,以便它改变:

self.admin_page_layout.addWidget(self.admin_page_switch, 0, 0)

到:

self.admin_page_layout.addWidget(self.admin_page_switch, 0, 0, alignment=QtCore.Qt.AlignCenter)

【讨论】:

以上是关于在 QStackedWidget 对象内定位内部小部件的主要内容,如果未能解决你的问题,请参考以下文章

将自定义小部件添加到 QStackedWidget

如何从 QStackedWidget 中删除所有小部件?

从另一个文件中的按钮切换 QStackedWidget 中的小部件

通过 QStackedWidget 动态修改同一个小部件的多个实例

将没有布局的 QWidget 添加到 QStackedWidget 镶嵌间隙

使用 Qt Creator 中设计的自定义小部件将页面动态添加到 QStackedWidget