在QScintilla插入编辑器中的图像

问题描述:

编辑:
标准QScintilla软件不支持此功能。但是Matic Kukovec做了一些攻击,无论如何得到它的工作。他的解决方案是在他的回答下面解释,也是对这个网页:https://qscintilla.com/insert-images/在QScintilla插入编辑器中的图像


我想在一个QScintilla编辑器中插入图像。不幸的是,这样的功能不会很快添加到官方的Scintilla项目中。看看这个职位上的Scintilla的,利益集团:

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

所以我必须实现它自己。我试了一下。请将以下代码复制到python文件中并运行它。只要确保你在同一个文件夹qscintilla_logo.png图像,约80×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脚本,你应该得到以下结果:

enter image description here

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

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

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

enter image description here

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

enter image description here

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


EDIT 1
的Python代码示例中的编辑器不执行任何语法突出显示,甚至不具有行号。那是因为我只想关注实际问题 - 添加图像。该代码示例是基于:


编辑2
请,请从在编辑器中插入图像是否是好还是坏主意提出意见避免。让我们继续关注技术问题。

+0

你试图实现这个的方式永远不会工作。小部件布局和文档布局是两个完全分开的东西。没有办法解决这个问题,因为Scintilla不支持将图像添加到文档布局。如果你真的想要这个功能,你需要寻找一个不同的代码编辑器小部件。 – ekhumoro

+0

谢谢ekhumoro您的评论。 “小部件布局”和“文档布局”是什么意思?我不会将图像添加到任何布局。事实上,我在它的“父”控件上给它一个绝对的位置。现在,我传递QScintilla编辑器作为父项,因为我没有别的。但我相信传递QScintilla编辑器的一个子部件 - 即滚动的部件 - 就是解决方案。 –

+0

如果用户在编辑器顶部插入/删除10行,您会发生什么?图像没有嵌入到文档布局中,因此在编辑文本时不会移动。如果你想嵌入图像,使用通用的富文本小部件,如'QTextEdit'。 – ekhumoro

嘿克里斯托夫试试这个(你有一些修改为例):

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中获得。 另一件事是我只是用行和列偏移硬编码图像的位置,创建一个编辑器可以自动解析和插入图像的语法可能会很好。

Regards

+0

谢谢马蒂奇! –