【问题标题】:Inserting an image in a QScintilla editor在 QScintilla 编辑器中插入图像
【发布时间】:2017-11-07 04:14:21
【问题描述】:

编辑:
标准的 QScintilla 软件不支持此功能。但是 Matic Kukovec 做了一些小技巧来让它正常工作。他的解决方案在下面的回答中进行了解释,但也在此网页上:https://qscintilla.com/insert-images/


我想在 QScintilla 编辑器中插入图像。不幸的是,这样的功能不会很快添加到官方的 Scintilla 项目中。查看 Scintilla-interest-group 上的这篇文章:

https://groups.google.com/forum/#!topic/scintilla-interest/Bwr4DY2Pv3Q

所以我必须自己实现它。我试了一下。请将以下代码复制粘贴到 python 文件中并运行它。只需确保您在同一文件夹中有一个 qscintilla_logo.png 图像,大约 80 x 80 像素:

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.Qsci import *

# -----------------------------------
# | A sample of C-code, pasted into |
# | the QScintilla editor           |
# -----------------------------------
myCodeSample = r"""#include <stdio.h>

/*
 * I want an image
 * right here =>
 */

int main()
{
    char arr[5] = {'h', 'e', 'l', 'l', 'o'};

    int i;

    for(i = 0; i < 5; i++) {
        printf(arr[i]);
    }

    return 0;

}""".replace("\n","\r\n")


# --------------------------------------------------

class CustomMainWindow(QMainWindow):
    def __init__(self):
        super(CustomMainWindow, self).__init__()

        # ---------------------------
        # |      Window setup       |
        # ---------------------------

        # 1. Define the geometry of the main window
        # ------------------------------------------
        self.setGeometry(300, 300, 800, 400)
        self.setWindowTitle("QScintilla Test")

        # 2. Create frame and layout
        # ---------------------------
        self.__frm = QFrame(self)
        self.__frm.setStyleSheet("QWidget { background-color: #ffeaeaea }")
        self.__lyt = QVBoxLayout()
        self.__frm.setLayout(self.__lyt)
        self.setCentralWidget(self.__frm)
        self.__myFont = QFont("Consolas", 14, weight=QFont.Bold)
        self.__myFont.setPointSize(14)

        # 3. Place a button
        # ------------------
        self.__btn = QPushButton("Qsci")
        self.__btn.setFixedWidth(50)
        self.__btn.setFixedHeight(50)
        self.__btn.clicked.connect(self.__btn_action)
        self.__btn.setFont(self.__myFont)
        self.__lyt.addWidget(self.__btn)

        # ---------------------------
        # | QScintilla editor setup |
        # ---------------------------

        # 1. Make instance of QSciScintilla class
        # ----------------------------------------
        self.__editor = QsciScintilla()
        self.__editor.setText(myCodeSample)
        self.__editor.setLexer(None)
        self.__editor.setUtf8(True)  # Set encoding to UTF-8
        self.__editor.setFont(self.__myFont)  # Can be overridden by lexer


        # 2. Create an image
        # -------------------
        self.__myImg = QPixmap("qscintilla_logo.png")
        self.__myImgLbl = QLabel(parent=self.__editor)
        self.__myImgLbl.setStyleSheet("QLabel { background-color : white; }");
        self.__myImgLbl.setPixmap(self.__myImg)
        self.__myImgLbl.move(300,80)


        # 3. Add editor to layout
        # ------------------------
        self.__lyt.addWidget(self.__editor)

        self.show()

    ''''''

    def __btn_action(self):
        print("Hello World!")

    ''''''


''' End Class '''

if __name__ == '__main__':
    app = QApplication(sys.argv)
    QApplication.setStyle(QStyleFactory.create('Fusion'))
    myGUI = CustomMainWindow()

    sys.exit(app.exec_())

''''''

 
运行 Python 脚本时,您应该得到以下结果:

我实际上是在编辑器的顶部添加一个QLabel ,并给它一个绝对位置:

        self.__myImgLbl = QLabel(parent=self.__editor)
        self.__myImgLbl.move(300,80)

不幸的是,向下滚动时图像不会移动:

我想我知道为什么。让我解释。编辑器是QsciScintilla类的对象,是QsciScintillaBase的子类,QAbstractScrollAreaQAbstractScrollArea的子类:

我相信成功的关键是将 QLabel 添加到 内部的小部件 QAbstractScrollArea,而不是滚动区域本身。我尝试了几件事来找到该小部件,但没有成功。
如果它是 QScrollArea,那么函数 widget() 就足够了。但是这个功能在QAbstractScrollArea上是不可用的。


编辑 1
python 代码示例中的编辑器不执行任何语法高亮,甚至没有行号。那是因为我只想关注实际问题 - 添加图像。代码示例基于:https://qscintilla.com/an-editor-in-a-gui/


编辑 2
请不要就在编辑器中插入图像是好主意还是坏主意发表意见。让我们坚持手头的技术问题。

【问题讨论】:

  • 你试图实现这一点的方式永远不会奏效。小部件布局和文档布局是两个完全不同的东西。您无法解决此问题,因为 Scintilla 不支持将图像添加到文档布局。如果你真的想要这个功能,你需要寻找一个不同的代码编辑器小部件。
  • 感谢 ekhumoro 的评论。 “小部件布局”和“文档布局”是什么意思?我没有将图像添加到任何布局中。事实上,我在它的parent 小部件之上给了它一个绝对位置。现在,我将 QScintilla 编辑器作为父级传递,因为我没有其他任何东西。但我相信传递 QScintilla 编辑器的一些子小部件 - 滚动的小部件 - 是解决方案。
  • 如果用户在编辑器顶部插入/删除 10 行,你认为会发生什么?图像未嵌入文档布局中,因此在编辑文本时不会移动。如果您想要嵌入图像,请使用通用的富文本小部件,例如 QTextEdit
  • 你是对的@ekhumoro。让它正常工作将是一个相当大的挑战。但是切换到 QTextEdit 也不是一个好的选择。它没有像 QScintilla 那样的词法分析器功能(用于高级语法突出显示)。而且它没有可点击的文本(就像 QScintilla 中的热点)。
  • QSyntaxHighlighter 用于词法分析。显然QTextEdit 确实有可点击的文本(即链接),因为它可以呈现 html。

标签: python pyqt pyqt5 scintilla qscintilla


【解决方案1】:

嘿 Kristof 试试这个(你的例子做了一些修改):

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.Qsci import *

# -----------------------------------
# | A sample of C-code, pasted into |
# | the QScintilla editor           |
# -----------------------------------
myCodeSample = r"""#include <stdio.h>

/*
 * I want an image
 * right here =>
 */

int main()
{
    char arr[5] = {'h', 'e', 'l', 'l', 'o'};

    int i;

    for(i = 0; i < 5; i++) {
        printf(arr[i]);
    }

    return 0;

}""".replace("\n","\r\n")


# --------------------------------------------------
class MyScintilla(QsciScintilla):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.image = QImage("qscintilla_logo.png")

    def paintEvent(self, e):
        super().paintEvent(e)
        # Get paint rectangle size
        current_parent_size = self.size()
        image_line = 4
        image_column = 17
        # Find the paint offset
        line_height = 20
        font_width = 10
        first_visible_line = self.SendScintilla(self.SCI_GETFIRSTVISIBLELINE)
        paint_offset_x = image_column * font_width
        paint_offset_y = (image_line - first_visible_line) * line_height
        # Paint the image
        painter = QPainter()
        painter.begin(self.viewport())
        painter.drawImage(QPoint(paint_offset_x,paint_offset_y), self.image)
        painter.end()


class CustomMainWindow(QMainWindow):
    def __init__(self):
        super(CustomMainWindow, self).__init__()

        # ---------------------------
        # |      Window setup       |
        # ---------------------------

        # 1. Define the geometry of the main window
        # ------------------------------------------
        self.setGeometry(300, 300, 800, 400)
        self.setWindowTitle("QScintilla Test")

        # 2. Create frame and layout
        # ---------------------------
        self.__frm = QFrame(self)
        self.__frm.setStyleSheet("QWidget { background-color: #ffeaeaea }")
        self.__lyt = QVBoxLayout()
        self.__frm.setLayout(self.__lyt)
        self.setCentralWidget(self.__frm)
        self.__myFont = QFont("Consolas", 14, weight=QFont.Bold)
        self.__myFont.setPointSize(14)

        # 3. Place a button
        # ------------------
        self.__btn = QPushButton("Qsci")
        self.__btn.setFixedWidth(50)
        self.__btn.setFixedHeight(50)
        self.__btn.clicked.connect(self.__btn_action)
        self.__btn.setFont(self.__myFont)
        self.__lyt.addWidget(self.__btn)

        # ---------------------------
        # | QScintilla editor setup |
        # ---------------------------

        # 1. Make instance of QSciScintilla class
        # ----------------------------------------
        self.__editor = MyScintilla()
        self.__editor.setText(myCodeSample)
        self.__editor.setLexer(None)
        self.__editor.setUtf8(True)  # Set encoding to UTF-8
        self.__editor.setFont(self.__myFont)  # Can be overridden by lexer


        # 3. Add editor to layout
        # ------------------------
        self.__lyt.addWidget(self.__editor)

        self.show()

    ''''''

    def __btn_action(self):
        print("Hello World!")

    ''''''


''' End Class '''

if __name__ == '__main__':
    app = QApplication(sys.argv)
    QApplication.setStyle(QStyleFactory.create('Fusion'))
    myGUI = CustomMainWindow()

    sys.exit(app.exec_())

''''''

它只是继承 QsciScintilla 类并重载它的 paintEvent 方法。 诀窍是获取图像相对于文档视图的坐标。对于我刚才猜到的行高和字体宽度的例子,它可能可以从 QScintilla 获得。 另一件事是我只是用行和列偏移对图像的位置进行了硬编码,创建一个编辑器可以自动解析和插入图像的语法可能会很好。

问候

【讨论】:

    猜你喜欢
    • 2011-09-05
    • 2016-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多