標籤:

PyQt5系列教程(32): 純文本輸入框(QPlainTextEdit)2--這次沒翻車

上期我們總體介紹了QPlainTextEdit的相關知識,並且簡單介紹了Python類中類的概念以及舉了一個生活中的小例子,本期我們繼續...

從圖像中可以看到,編輯器在區域左側的區域中顯示行號進行編輯。編輯器將突出顯示包含游標的行。

我們在QCodeEditor中實現了編輯器,它是一個繼承QPlainTextEdit的控制項。我們在QCodeEditor中保留一個單獨的小部件,我們在其中繪製行號。

QPlainTextEdit從QAbstractScrollArea繼承,編輯發生在其viewport()的邊緣。我們通過將視口(viewport,下同)的左邊距設置為繪製行號所需的大小,為我們的行號區域騰出空間。

在編輯代碼時,我們比QTextEdit更喜歡QPlainTextEdit,因為它為處理純文本而優化。

現在我們將繼續學習QCodeEditor和NumberBar的定義和實現。我們從NumberBar類開始。

我們在這個小部件上繪製行號,並將它放在QCodeEditor的viewport()的左邊空白處。

在繪製區域時,為了簡單起見,我們在QCodeEditor類中繪製區域。我們可以直接在代碼編輯器上繪製行號,並刪除NumberBar類。但是,QWidget類可以幫助我們scroll() 其內容。此外,如果我們希望使用斷點或其他代碼編輯器功能擴展編輯器,則擁有單獨的窗口小部件是正確的選擇。該小部件將幫助處理滑鼠事件。

so,知道我們為什麼要用類中類了吧!

QCodeEditor類

class QCodeEditor(QPlainTextEdit): class NumberBar(QWidget): pass def __init__(self): super(QCodeEditor, self).__init__() self.setWindowTitle(微信公眾號:學點編程吧--帶行號和顏色的文本框) self.setFont(QFont("Ubuntu Mono", 12)) self.setLineWrapMode(QPlainTextEdit.NoWrap) self.number_bar = self.NumberBar(self) self.currentLineNumber = None self.cursorPositionChanged.connect(self.highligtCurrentLine) self.setViewportMargins(40, 0, 0, 0) self.highligtCurrentLine() def resizeEvent(self, *e): cr = self.contentsRect() rec = QRect(cr.left(), cr.top(), self.number_bar.getWidth(), cr.height()) self.number_bar.setGeometry(rec) def highligtCurrentLine(self): newCurrentLineNumber = self.textCursor().blockNumber() if newCurrentLineNumber != self.currentLineNumber: lineColor = QColor(Qt.yellow).lighter(160) self.currentLineNumber = newCurrentLineNumber hi_selection = QTextEdit.ExtraSelection() hi_selection.format.setBackground(lineColor) hi_selection.format.setProperty(QTextFormat.FullWidthSelection, True) hi_selection.cursor = self.textCursor() hi_selection.cursor.clearSelection() self.setExtraSelections([hi_selection])

QCodeEditor繼承了QPlainTextEdit類。在這個類中,我們進行了一些簡單窗體屬性設置,設置了視口、突出顯示包含游標的行和重寫了resizeEvent()事件。下面對已有的前面教程中尚未出現過的代碼解釋一下。

self.setFont(QFont("Ubuntu Mono", 12))

設置當前的字體和大小,這個可以隨意,無所謂的。

self.setLineWrapMode(QPlainTextEdit.NoWrap)

該屬性包含換行模式,默認模式是QPlainTextEdit.WidgetWidth,即類似於記事本中的自動換行,一行文字過長會換一行。文中使用QPlainTextEdit.NoWrap表明這個文件我不願意自動換行,一行較長的文字就要在一行當中。

self.number_bar = self.NumberBar(self) self.currentLineNumber = None

實例化我們的內部類,同時將當前需要標記的行號初始值為None。

self.cursorPositionChanged.connect(self.highligtCurrentLine)

cursorPositionChanged()是QPlainTextEdit所帶的信號,表明只要游標位置改變,就會發出此信號,然後我們調用對應的自定義槽函數highligtCurrentLine(),也就是把當前行標黃。

self.setViewportMargins(40, 0, 0, 0)self.highligtCurrentLine()

setViewportMargins()這個方法來源於QPlainTextEdit的父類QAbstractScrollArea,將滾動區域周圍的邊距設置為左側,頂部,右側和底部(我們這裡是左側)。 邊緣空間是空白的。 將小部件放在未使用的區域。默認情況下,所有邊距都為零。

為什麼要增加這兩句呢?注釋掉這兩句看看效果吧。

注釋後的

未注釋的

注釋之後,我們在輸入的時候明顯的會看到兩點:1、部分字母被擋著了;2、沒有黃色的標記了。這其實就是原作者的bug,增加了這兩句就能更加的符合使用習慣了。

def resizeEvent(self, *e): cr = self.contentsRect() rec = QRect(cr.left(), cr.top(), self.number_bar.getWidth(), cr.height()) self.number_bar.setGeometry(rec)

此事件處理程序可以在子類中重新實現,以接收在事件參數中傳遞的小部件大小調整事件。當調用resizeEvent()時,窗口小部件已經有了新的幾何圖形。 舊尺寸可通過QResizeEvent.oldSize()訪問。

cr = self.contentsRect()

返回小部件邊界內的區域。

rec = QRect(cr.left(), cr.top(), self.number_bar.getWidth(), cr.height())self.number_bar.setGeometry(rec)

創建一個QRect對象,使用整數精度在平面中定義一個矩形,這裡是用一組左,頂,寬和高整數來定義。矩形通常表示為左上角和大小。QRect的大小(寬度和高度)始終等同於構成其渲染基礎的數學矩形。當然QRect也可以從QPoint和QSize構成。

然後我們將這個矩形應用到number_bar這個自定義小部件上,那麼它的大小就確定了。

def highligtCurrentLine(self): newCurrentLineNumber = self.textCursor().blockNumber() if newCurrentLineNumber != self.currentLineNumber: lineColor = QColor(Qt.yellow).lighter(160) self.currentLineNumber = newCurrentLineNumber hi_selection = QTextEdit.ExtraSelection() hi_selection.format.setBackground(lineColor) hi_selection.format.setProperty(QTextFormat.FullWidthSelection, True) hi_selection.cursor = self.textCursor() hi_selection.cursor.clearSelection() self.setExtraSelections([hi_selection])

這個函數就是用來突出顯示包含游標的行。

newCurrentLineNumber = self.textCursor().blockNumber()

返回遊標所在塊的編號,如果游標無效,則返回0。請注意,此功能僅適用於沒有複雜對象(如表格或框架)的文檔。

if newCurrentLineNumber != self.currentLineNumber:

看到沒有,這裡表示游標換行了。

lineColor = QColor(Qt.yellow).lighter(160)

這裡我搞的是黃色,紅色、黑色、藍色隨便你選。

hi_selection = QTextEdit.ExtraSelection() hi_selection.format.setBackground(lineColor)hi_selection.format.setProperty(QTextFormat.FullWidthSelection, True)

QTextEdit.ExtraSelection結構提供了一種為文檔中已選擇指定字元格式的方法。

hi_selection.format.setBackground(lineColor)

一種格式,用於指定選區的前景或背景畫筆/顏色。我這裡是設定背景色。

hi_selection.format.setProperty(QTextFormat.FullWidthSelection, True)

設定文本的整個寬度將顯示為選中狀態。

hi_selection.cursor = self.textCursor()hi_selection.cursor.clearSelection()

通過將錨點設置為游標位置來清除當前選擇。請注意,它不會刪除選擇的文本。

self.setExtraSelections([hi_selection])

此功能允許用指定的顏色臨時標記文檔中的某些區域,並將其指定為選項。 記住()裡面是列表的形式。

NumberBar類的講解放到下章吧,內容太多了。碼字也很累啊!

最後

ok,今天的介紹就到這裡吧,下期我們繼續。如果你喜歡本篇文章,請給我點贊

讚賞(推薦

分享給你的好友們吧!

關注微信公眾號:學點編程吧,你可以學到更多!源碼講解完了一起再發,發送方式還是老規矩。

推薦閱讀:

如何學習Python 標準庫的問題
這或許是對小白最友好的python入門了吧——10,元組
如何把嵌套的python list轉成一個一維的python list?
給妹子講python--21函數參數的匹配與解包
如何學習Python?

TAG:PyQt | PyQt5 | | Python |