对话框页面

在pyminer中自带一个对话框插件,点击之后,可以获取工作空间变量、向控制台注入命令并且显示。 这个插件是如何实现的呢?请让我们继续往下看。 对话框插件位置

源文件解析

它的源文件位置为(pyminer2/extensions/packages/extension_dialog_demo),如图所示: 输入图片说明

json编写

{
  "name": "extension_dialog_demo",
  "display_name": "对话框插件demo",
  "version": "0.1",
  "description": "好多介绍",
  "icon": "python.jpg",
  "interface": {
    "file": "main.py",
    "interface": "Interface"
  },
  "widgets": [
    {
      "file": "main.py",
      "widget": "DemoToolButton",
      "position": "append_to_toolbar",
      "config": {
        "toolbar": "toolbar_home",
        "message": "no",
        "name": "demo_tool_button"
      }
    }
  ],
  "requirements": [
  ]
}

在以上的json中,我们可以发现这几个信息:

  • 1、我们的对话框窗体类,并没有在json中体现出来。json中只注册了一个DemoToolButton。看名字的话,这像是一个工具栏按钮。 没错,就是这样的。对话框在唤出时动态生成,关闭之后就释放掉了。这样可以节省不少内存。

  • 2、我们需要改写的主要是"widgets"的"config"属性。其中比较重要的是: -- toolbar参数。这个参数的可以说明将这个东西插入到哪个工具栏中。而toolbar_home的意思就是主页工具栏。目前只有主页工具栏,所以就插入主页中。 -- message参数:用处不大。 -- name参数:按钮控件的名称。

main.py文件解析

"""
作者:@吴宫幽径
说明:
dialog无需写在json里面,直接调用主界面的控件就可以了。
"""
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog, QHBoxLayout, QToolButton, QTextEdit, QSizePolicy
from pyminer2.extensions.extensionlib import BaseExtension,BaseInterface

class Extension(BaseExtension):
    def on_load(self):
        self.demo_tool_button = self.widgets['DemoToolButton']
        self.demo_tool_button.extension_lib = self.extension_lib
        print("对话框示例被加载")

    def on_install(self):
        print('被安装')

    def on_uninstall(self):
        print("被卸载")


class Interface(BaseInterface):
    def hello(self):
        print("Hello,来自对话框示例")


class DemoToolButton(QToolButton):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setText('显示\n插件示例\n的对话框')
        self.clicked.connect(self.show_dialog)

    def show_dialog(self):
        """
        显示一个插件示例所弹出的对话框。
        """
        self.demo_tool_dialog = DemoToolDialog(self, ['执行python命令\'x=123\'', '获取数据x值\n', ])
        self.demo_tool_dialog.extension_lib = self.extension_lib
        self.demo_tool_dialog.show()


class DemoToolDialog(QDialog):
    def __init__(self, parent, button_text: list):
        super().__init__(parent)
        layout = QHBoxLayout(self)
        self.text_edit = QTextEdit()
        self.text_edit.append('请先点击左侧按钮运行命令\'x=123\',然后点击右侧按钮获取变量空间中的x值。'
                              '\n这条命令将以用户不可见的形式执行。\n')
        layout.addWidget(self.text_edit)
        b = QToolButton(self)
        b.setText(button_text[0])
        b.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
        b.clicked.connect(self.run_shell_command)
        layout.addWidget(b)
        b = QToolButton(self)
        b.setText(button_text[1])
        b.clicked.connect(self.get_data)
        b.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        layout.addWidget(b)
        self.setLayout(layout)

    def run_shell_command(self):
        console = self.extension_lib.get_interface('ipython_console')
        if console is None:
            raise Exception('dependency ipython console not found')
        console.run_command(command='x=123',hint_text='执行命令',hidden=False)
        self.text_edit.append('命令已执行,请查看工作空间。\n')
        self.extension_lib.UI.raise_dock_into_view('ipython_console')#调用命令,将控制台提升到窗口最上方。

    def get_data(self):
        try:
            var = self.extension_lib.get_var('x')
        except:
            self.text_edit.append('x变量不存在,请先点击左侧按钮对x赋值。\n')
            return
        self.text_edit.append('成功获取变量‘x’,值为' + repr(var) + '\n你可以在控制台中运行命令改变x的值,'
                                                           '并且再次点击右侧按钮获取它,查看有无变化。\n')

    def closeEvent(self, a0: 'QCloseEvent') -> None:
        '''
        保证插件的退出动作,不会影响到主界面的其他部位。
        '''
        a0.accept()
        self.deleteLater()


if __name__ == '__main__':
    '''
    这个测试只是用于调试界面,不能点击按钮
    '''
    from PyQt5.QtWidgets import QApplication
    import sys
    app = QApplication(sys.argv)
    form = DemoToolDialog(None,['aaa','dddddd'])
    form.show()
    sys.exit(app.exec_())

一共有四个类——Interface,Extension,DemoToolButton,DemoToolDialog。 Interface和Extension是基础教程中已经说明过的模板类,在这里不再赘述。

DemoToolButton

DemoToolButton是一个插入工具栏的按钮,在json中需要注册它的名称。

当点击的时候,调用show_dialog方法,直接唤出DemoToolDialog对话框。

DemoToolDialog

这是一个对话框类。

说到对话框,你很可能想到的是弹出一条错误信息,只给你留一两个按钮的小窗体。但实际上对话框可以做的很大很大。

当然你可以发现,这个类与其他的对话框最大的不同就是,它调用了插件接口extension_lib,这个插件接口却依赖于主界面。如果主界面不启动,那么插件是不可能独立运行的,调试的确带来了一定的不便。但是,如果不调用extension_lib这个接口,插件的意义又何在呢?

因此,对开发者的建议是,可以先写好界面中不依赖pyminer主程序的部分。加上接口之后,就要插入到Pyminer主程序上面调试了。我们的主界面已经初步优化了启动速度,它的启动时间并不会太长,而且未来还将继续优化,从而为开发者提供更加快捷高效的开发体验。

回到对话框。尽管我不得不承认,这个对话框界面做的非常非常难看——但是它好歹体现了两种基本操作:在控制台中运行命令,以及获取工作空间的数据。

1、在控制台中运行命令。

extension_lib.run_command_in_console('x=123',,hint='执行命令') 这一句代码可以运行命令。x=123。hint则是显示的提示文字。

2、获取工作空间的数据。

extension_lib.get_var('x')。

这句代码的意思是获取工作空间的数据,数据的变量名为x。

当然,如果你问:“如果,我想在对话框中嵌入一个列表框,把工作区里面全部的变量名称都显示出来,点击某个变量的时候,就加载它到表格里/在绘图窗口中绘制出来/存储为文件/(...以下省略n种可能的操作),你说这样可以吗?”

答案当然是肯定的。不过,在这里篇幅所限,不能多说了。其余更多方法,请参阅插件接口的文档!

3、提升窗口

细心如你,可能注意到了以下语句:

extension_lib.raise_dock_into_view(extension_lib.CONSOLE_WIDGET)

这个语句是什么意思呢?答案是将窗口提升到最上方。

PyMiner的主界面中,除了工具栏就是可停靠窗口(继承于QDockWidget)。可停靠窗口既可以单独停靠在主界面之上,又可以摞在一起,就像选项卡那样————但显而易见,它们和选项卡不同,因为选项卡控件的标签在上方,而可停靠窗口的标签在下方。

红圈是可停靠窗口的标签,绿圈是选项卡的标签。

当这些控件摞在一起的时候,就会出现一个问题————假如说控制台不在最上层,你在对话框中执行命令,那么要观察控制台中的变化,你还要点击一次控制台的标签。如果反复执行不同的命令,就要这样来回点来点去,烦煞我也。

为了解决这种令用户抓狂不已的问题,Pyminer引入了“提升窗口到可见”的功能。而这句代码的意思,就是将控制台窗口提升到最上方,使得其可见。

执行前后窗口截图如下:

执行前

输入图片说明

执行后

执行后

你可以将和控制台叠放在一起的其他窗口置于最上方,再次点击这个对话框的按钮运行命令,你会发现控制台自动蹦到了可见的位置。这就是这条命令的威力。

Note:执行python console命令的时候,不会显示命令的文字,但是可以看到行数在增加,这是正常现象。

results matching ""

    No results matching ""