交互式python - 使用GUI mainloop保持控制台交互

时间:2014-10-05 20:53:03

标签: python user-interface console nonblocking interactive

我想知道如何创建一个GUI应用程序,并从启动它的控制台与它进行交互。

作为一个例子,我想在PyQt中创建一个GUI并从控制台中使用它。这可以用于测试设置而无需重新启动应用程序,但在较大的项目中也可用于调用函数等。

以下是使用PyQt的简单示例:

import sys
from PyQt4 import QtGui

def main():
  app = QtGui.QApplication(sys.argv)
  w = QtGui.QWidget()
  w.show()
  sys.exit(app.exec_())

if __name__ == '__main__':
    main()

当使用python -i example.py运行时,只要执行主循环,控制台就会被阻止。

如何在GUI运行时调用w.resize(100,100)

3 个答案:

答案 0 :(得分:0)

ops,在

之前发布了错误答案

Stack中有一篇关于

的帖子

Execute Python code from within PyQt event loop

答案 1 :(得分:0)

最简单的方法是使用IPython:

ipython --gui=qt4

有关更多选项(例如gtk,tk等),请参阅ipython --helponline documentation

答案 2 :(得分:0)

下面的示例使用code模块在​​命令提示符下运行控制台(请确保从命令行运行脚本)。 Subclassing QThread提供了一种途径,使控制台可以在与主GUI不同的线程中运行,并可以进行一些交互。下面的存根示例应该足够容易地集成到更大的打包的PyQt程序中。

from PyQt5.QtWidgets import * 
from PyQt5.QtCore import *

import threading #used only to id the active thread
import code
import sys

class Worker(QThread): #Subclass QThread and re-define run() 
    signal = pyqtSignal()

    def __init__(self):
        super().__init__()

    def raise_sys_exit(self): #more gracefully exit the console
        print('(Deactivated Console)')
        raise SystemExit

    def setup_console(self,global_dict):
        console_exit = {'exit': self.raise_sys_exit}
        self.console = code.InteractiveConsole(locals=dict(global_dict,**console_exit))

    def run(self):
        try:
            print('worker', threading.get_ident())
            self.console.interact()
        except SystemExit:
            self.signal.emit()

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

        self.data = [1,2,3,4] #some data we might want to look at

        layout = QVBoxLayout()
        self.b = QPushButton("Interact")
        self.b.clicked.connect(self.b_clicked)
        layout.addWidget(self.b)

        w = QWidget()
        w.setLayout(layout)
        self.setCentralWidget(w)

        self.worker = Worker()
        self.worker.signal.connect(self.finished)

    def finished(self):
        self.b.setEnabled(True)

    def b_clicked(self):
        print('main',threading.get_ident())
        self.worker.setup_console(globals()) #pass the global variables to the worker
        self.worker.start()
        self.b.setEnabled(False) #disable the GUI button until console is exited

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()

    app.exec_()