如何在一个主窗口中有两个小部件 [英] How to have two widgets in one Main window

查看:41
本文介绍了如何在一个主窗口中有两个小部件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我整个上午都在努力解决这个问题.所以我有一个 PyQt 主窗口,我想在其中显示两个小部件.在第一个小部件中列出了文章(到目前为止有效).当我点击它们直到现在 QMessageBox 正在打开时,但我想要那个第二个小部件正在打开,我可以在其中阅读 RSS 源.但这是行不通的.请参阅下面的代码:

class ArticleWidgets(QWidget):def __init__(self, *args):super().__init__(*args)self.setGeometry(610, 610, 600, 600)self.initUi()定义 initUi(self):self.box = QHBoxLayout(self)def show(self, feed=None):self.title = QLabel()self.summary = QLabel()self.link = QLabel()如果饲料:self.title.setText(feed[0])self.summary.setText(feed[1])self.link.setText(feed[2])self.box.addWidget(self.title)self.box.addWidget(self.summary)self.box.addWidget(self.link)self.setLayout(self.box)类 TitleWidgets(QWidget):def __init__(self, *args):super().__init__(*args)self.setGeometry(10, 10, 600, 600)self.initUi()定义 initUi(self):vbox = QHBoxLayout(self)self.titleList = QListWidget()self.titleList.itemDoubleClicked.connect(self.onClicked)self.titleList.setGeometry(0, 0, 400, 400)self.news = ANFFeed()对于 self.news.all_feeds 中的项目:self.titleList.addItem(item[0])vbox.addWidget(self.titleList)def onClicked(self, item):feeds = self.news.all_feeds编号 = 0对于范围内的元素(len(feeds)):如果 feeds[elem][0] == item.text():id = 元素摘要 = feeds[id][1] + '\n\n'链接 = feeds[id][2]如果提要和 ID:#ANFApp(self).show_articles(feeds[id])显示 = ANFApp()show.show_articles(feed=feeds[id])QMessageBox.information(self, 'Details', summary + link)类 ANFApp(QMainWindow):def __init__(self, *args):super().__init__(*args)self.setWindowState(Qt.WindowMaximized)self.setWindowIcon(QIcon('anf.png'))self.setAutoFillBackground(True)self.anfInit()自我展示()def anfInit(self):self.setWindowTitle('ANF RSS 阅读器')TitleWidgets(self)#article_box = ArticleWidgets(self)exitBtn = QPushButton(self)exitBtn.setGeometry(600, 600, 100, 50)exitBtn.setText('退出')exitBtn.setStyleSheet("background-color: red")exitBtn.clicked.connect(self.exit)def show_articles(self, feed=None):存在 = 文章小部件()present.show(饲料)定义退出(自我):QCoreApplication.instance().quit()

解决方案

使用 Pyqtgraph 的 Docks 和 QTextBrowser 的解决方案

这是一个试图重现你的草图的代码.我使用了 Pyqtgraph 模块(此处的文档:

如果您在两个小部件之间传递鼠标,您将看到鼠标图标会发生变化,您可以在运行时重新调整两个小部件的大小.

最后的话

这是另一种方法,更具互动性";比我之前的答案更美观.正如您所说,使用 QSplitter 也可以.

I am trying the whole morning already to fix that. So I have a PyQt Main Window where I want to display two widgets. In the first widget there are articles listed (which works so far). When I click on them until now a QMessageBox is opening, but I want that a second widget is opening where I can read the RSS Feed. But this is not working. See Code below:

class ArticleWidgets(QWidget):
    def __init__(self, *args):
        super().__init__(*args)

        self.setGeometry(610, 610, 600, 600)

        self.initUi()

    def initUi(self):
        self.box = QHBoxLayout(self)

    def show(self, feed=None):

        self.title = QLabel()
        self.summary = QLabel()
        self.link = QLabel()

        if feed:
            self.title.setText(feed[0])
            self.summary.setText(feed[1])
            self.link.setText(feed[2])

        self.box.addWidget(self.title)
        self.box.addWidget(self.summary)
        self.box.addWidget(self.link)

        self.setLayout(self.box)


class TitleWidgets(QWidget):
    def __init__(self, *args):
        super().__init__(*args)

        self.setGeometry(10, 10, 600, 600)

        self.initUi()

    def initUi(self):
        vbox = QHBoxLayout(self)

        self.titleList = QListWidget()
        self.titleList.itemDoubleClicked.connect(self.onClicked)
        self.titleList.setGeometry(0, 0, 400, 400)
        self.news = ANFFeed()
        for item in self.news.all_feeds:
            self.titleList.addItem(item[0])
        vbox.addWidget(self.titleList)

    def onClicked(self, item):
        feeds = self.news.all_feeds
        id = 0
        for elem in range(len(feeds)):
            if feeds[elem][0] == item.text():
                id = elem

        summary = feeds[id][1] + '\n\n'
        link = feeds[id][2]

        if feeds and id:
            #ANFApp(self).show_articles(feeds[id])
            show = ANFApp()
            show.show_articles(feed=feeds[id])

        QMessageBox.information(self, 'Details', summary + link)


class ANFApp(QMainWindow):
    def __init__(self, *args):
        super().__init__(*args)

        self.setWindowState(Qt.WindowMaximized)
        self.setWindowIcon(QIcon('anf.png'))
        self.setAutoFillBackground(True)

        self.anfInit()

        self.show()

    def anfInit(self):
        self.setWindowTitle('ANF RSS Reader')

        TitleWidgets(self)
        #article_box = ArticleWidgets(self)

        exitBtn = QPushButton(self)
        exitBtn.setGeometry(600, 600, 100, 50)
        exitBtn.setText('Exit')
        exitBtn.setStyleSheet("background-color: red")
        exitBtn.clicked.connect(self.exit)

    def show_articles(self, feed=None):
        present = ArticleWidgets()
        present.show(feed)

    def exit(self):
        QCoreApplication.instance().quit()

解决方案

Solution using Pyqtgraph's Docks and QTextBrowser

Here is a code trying to reproduce your sketch. I used the Pyqtgraph module (Documentation here: Pyqtgraph's Documentation and Pyqtgraph's Web Page) because its Dock widget is easier to use and implement from my perspective.

You must install the pyqtgraph module before trying this code:

import sys
from PyQt5 import QtGui, QtCore
from pyqtgraph.dockarea import *

class DockArea(DockArea):
    ## This is to prevent the Dock from being resized to te point of disappear
    def makeContainer(self, typ):
        new = super(DockArea, self).makeContainer(typ)
        new.setChildrenCollapsible(False)
        return new

class MyApp(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        central_widget = QtGui.QWidget()
        layout = QtGui.QVBoxLayout()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)
    
        label = QtGui.QLabel('This is a label, The widgets will be below')
        label.setMaximumHeight(15)
        ## The DockArea as its name says, is the are where we place the Docks
        dock_area = DockArea(self)
        ## Create the Docks and change some esthetic of them
        self.dock1 = Dock('Widget 1', size=(300, 500))
        self.dock2 = Dock('Widget 2', size=(400, 500))
        self.dock1.hideTitleBar()
        self.dock2.hideTitleBar()
        self.dock1.nStyle = """
        Dock > QWidget {
            border: 0px solid #000;
            border-radius: 0px;
        }"""
        self.dock2.nStyle = """
        Dock > QWidget {
            border: 0px solid #000;
            border-radius: 0px;
        }"""
        self.button = QtGui.QPushButton('Exit')
        self.widget_one = WidgetOne()
        self.widget_two = WidgetTwo()
        ## Place the Docks inside the DockArea
        dock_area.addDock(self.dock1)
        dock_area.addDock(self.dock2, 'right', self.dock1)
        ## The statment above means that dock2 will be placed at the right of dock 1
        layout.addWidget(label)
        layout.addWidget(dock_area)
        layout.addWidget(self.button)
        ## Add the Widgets inside each dock
        self.dock1.addWidget(self.widget_one)
        self.dock2.addWidget(self.widget_two)
        ## This is for set the initial size and posotion of the main window
        self.setGeometry(100, 100, 600, 400)
        ## Connect the actions to functions, there is a default function called close()
        self.widget_one.TitleClicked.connect(self.dob_click)
        self.button.clicked.connect(self.close)
        
    def dob_click(self, feed):
        self.widget_two.text_box.clear()
        ## May look messy but wat i am doing is somethin like this:
        ## 'Title : ' + feed[0]  + '\n\n' + 'Summary : ' + feed[1]
        self.widget_two.text_box.setText(
            'Title : ' + feed[0]\
            + '\n\n' +\
            'Summary : ' + feed[1]
        )
        
class WidgetOne(QtGui.QWidget):
    ## This signal is created to pass a "list" when it (the signal) is emited
    TitleClicked = QtCore.pyqtSignal([list])
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.layout = QtGui.QVBoxLayout()
        self.setLayout(self.layout)
        self.titleList = QtGui.QListWidget()
        self.label = QtGui.QLabel('Here is my list:')
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.titleList)
        
        self.titleList.addItem(QtGui.QListWidgetItem('Title 1'))
        self.titleList.addItem(QtGui.QListWidgetItem('Title 2'))
        self.titleList.itemDoubleClicked.connect(self.onClicked)

    def onClicked(self, item):
        ## Just test values
        title = item.text()
        summary = "Here you will put the summary of {}. ".format(title)*50
        ## Pass the values as a list in the signal. You can pass as much values
        ## as you want, remember that all of them have to be inside one list
        self.TitleClicked.emit([title, summary]) 

class WidgetTwo(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.layout = QtGui.QVBoxLayout()
        self.setLayout(self.layout)
        self.label2 = QtGui.QLabel('Here we show results?:')
        self.text_box = QtGui.QTextBrowser()
        
        self.layout.addWidget(self.label2)
        self.layout.addWidget(self.text_box)

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

Again, there are comments inside the code to help you understand what I did. Here is how it looks:

If you pass the mouse between the two widgets you will see the mouse icon will change, with that you can readjust on the run the size of both widgets.

Final Words

This is another approach, more "interactive" and more esthetic than my previous answer. As you said, using a QSplitter works too.

这篇关于如何在一个主窗口中有两个小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆