PyQt5的怪异行为-主窗口无法启动

时间:2019-03-08 12:00:15

标签: python pyqt pyqt5 qtablewidget peewee

试图开发一种自动化工具,该工具为现有的Peewee(my favorite ORM)模型创建一个PyQt5 QTableWidget和一个QFormLayout上的输入对话框。

好吧-首先,我写了peewee模拟:

import logging
import sys

from PyQt5.QtWidgets import \
    QApplication, QWidget, QVBoxLayout, \
    QTableWidget, QTableWidgetItem
from PyQt5.QtCore import Qt


class MockedField:
    """to simulate Peewee fields"""
    def __init__(self, name):
        self.name = name


class MockedModel:
    """to simulate peewee model"""
    columns = [MockedField("name"),
               MockedField("firstname"),
               MockedField("nickname"),
               MockedField("email")]

    @classmethod
    def get_columnlist(cls):
        return cls.columns

之后,使用Qt5小部件的视图的基类。 他们 modelclass arg用于继承的peewee模型 由具有方法 get_columnlist()的类 BaseModel 组成。此方法返回所有peewee字段信息。

class _QtPeewee(QWidget):
    def __init__(self, modelclass, **opts):
        """Options:

            - parent (default=None)
            - minheight (default=600)
            - minwidth (default=1200)

        """
        parent = opts.get("parent", None)
        super().__init__(parent)

        self._minheight = opts.get("minheight", 600)
        self._minwidth = opts.get("minwidth", 1200)

        self.options = opts

        self.model = modelclass
        self.fields = modelclass.get_columnlist()
        self.fieldnames = [s.name.upper() for s in self.fields]

    def _setup_layout(self):
        logging.debug("<{}._setup_layout>".format(
            self.__class__.__name__))

        self.setMinimumHeight(self._minheight)
        self.setMinimumWidth(self._minwidth)

        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

    def _setup_widgets(self):
        raise RuntimeError("to implement in subclass!")

    def _connect_evt_with_handler(self):
        raise RuntimeError("to implement in subclass!")

    # UI

    def setup(self):
        logging.debug("<{}.setup()>".format(self.__class__.__name__))
        self._setup_layout()
        self._setup_widgets()
        self._connect_evt_with_handler()

然后使用QTableWidget通过peewee代表数据库数据的Widget:

class QtPeeweeTable(_QtPeewee):
    def __init__(self, modelclass, **opts):
        """further Opts:

            - datasets_per_page (default=15): -1 => shows all

                for the paginate(pageno, datasets_per_page) 
                method of peewee:
                http://docs.peewee-orm.com/en/latest/peewee/api.html#Query.paginate

        """
        super().__init__(modelclass, **opts)
        self._datasets_per_page = opts.get("datasets_per_page", 30)
        self.tbl = None

    def _setup_table(self) -> QTableWidget:
        logging.debug("<{}._setup_table()>".format(
            self.__class__.__name__))

        colnames = self.fieldnames
        self.tbl = tbl = QTableWidget(
            self._datasets_per_page, len(colnames))
        tbl.setHorizontalHeaderLabels(colnames)
        for r in range(self._datasets_per_page):
            for c in range(len(colnames)):
                tbl.setItem(r, c, QTableWidgetItem(""))
        return tbl

    def _setup_widgets(self):
        logging.debug("<{}._setup_widgets()>".format(
            self.__class__.__name__))

        tbl = self._setup_table()

        # table for ctx menu
        tbl.verticalHeader().setContextMenuPolicy(
            Qt.CustomContextMenu)
        tbl.horizontalHeader().setContextMenuPolicy(
            Qt.CustomContextMenu)

        self.layout.addWidget(self.tbl)

    def _connect_evt_with_handler(self):
        logging.debug("<{}._connect_evt_with_handler()>".format(
            self.__class__.__name__))
        # TODO

然后我尝试对其进行简单测试-令我惊讶的是,没有出现Qt5窗口??

def _test_mockmodel():
    view = QtPeeweeTable(modelclass=MockedModel)
    view.setup()
    view.show()


def main_not_running():
    logging.basicConfig(level=logging.DEBUG)
    app = QApplication(sys.argv)
    _test_mockmodel()
    sys.exit(app.exec_())

但是如果我在主要功能中实施测试,则窗口将启动:

def main_running():
    logging.basicConfig(level=logging.DEBUG)
    app = QApplication(sys.argv)

    view = QtPeeweeTable(modelclass=MockedModel)
    view.setup()
    view.show()

    sys.exit(app.exec_())


if __name__ == '__main__':
    main_not_running()
    # main_running()

我认为Qt5 app 对象必须在启动Qt进程的函数中-但是我没有在Qt文档中了解到它。如果我在未运行的测试功能中插入 app 对象,则窗口将启动:

def _test_mockmodel(app):
    view = QtPeeweeTable(modelclass=MockedModel)
    view.setup()
    view.show()
    sys.exit(app.exec_())


def main_not_running():
    logging.basicConfig(level=logging.DEBUG)
    app = QApplication(sys.argv)
    _test_mockmodel(app)

0 个答案:

没有答案