2017-06-06 72 views
0

編輯:
標準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

回答

1

嘿克里斯托夫試試這個(你有一些修改爲例):

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

謝謝馬蒂奇! –