天天看點

QSS——實作ColorLabel

作者:C加加Qt技術開發老傑

需求分析

我們想要在界面中讓文本顯示出指定的顔色,現在有幾種方案:

  1. 使用paintEvent手動計算文字大小和位置,然後繪制
  2. 利用QLabel可以識别HTML标簽的特性實作彩色文字
  3. 利用QSS+QLabel實作彩色文字

我們逐一分析這三種方案的利弊。

首先是paintEvent的方案,這是三種方案中最靈活卻也是最複雜的,通過重繪事件可以最大限度的發揮其靈活性,但對于字型大小的計算以及文字對齊的控制都需要自行處理,如此一來工程量不可謂不大,顯然對于我們隻是希望讓文字顯示出指定顔色的簡單需求來說實作成本過高了。

其次是使用HTML标簽的方案,這種方案的好處在于QLabel已經幫我們處理了文字的繪制和對齊,我們隻需要将合适的HTML内容添加進去即可,雖然靈活性不如第一種,但是其簡便性是顯而易見的,例如:

label = QLabel(r'<font color="#ff0000">Qt</font>')label.show()           

這将會顯示一個紅色的“Qt”文字。

點選檢視→Qt開發必備技術棧以及學習資料

然而該方案的缺點也是顯而易見的,雖然QLabel識别了HTML标簽并且不會明文顯示,但它确是實際存在于label中的:

print(label.text()) # '<font color="#ff0000">Qt</font>'           

當我們需要設定/擷取label中的文字時,就不得不想辦法去除這個HTML标簽,又或者當我們想要修改label的顔色時,就不得不對text做更複雜的處理,顯然,我們的需求中也會包含以上類似的場景,是以這種看起來簡單實際上暗含了複雜性的方案我也沒有采用。事實上開發中經常會出現這種坑,是以在方案選擇時三思而後行總是有好處的。

最後一種是QSS+QLabel的方案,也是目前我采用的方案。你可能已經猜到了,這種方案兼具QLabel的實用和QSS的簡單,也不會在内部儲存多餘的資訊,在犧牲部分靈活性的前提下是最簡單也是最合适的解決方案,接下來我們就詳細了解下這種方案的實作。

ColorLabel的實作

所有的代碼在這裡,具體使用可以在我的項目中看到。

首先是定義預設顔色和QSS模闆,模闆用于後續的顔色設定:

var (	// 控制顔色的qss模闆	colorStyle = "QLabel{color:%s;}"	// 預設顔色-黑色	defaultStyle = "QLabel{color:black;}")           

其實空字元串""就表示使用系統自帶樣式,然而我這裡為了統一就選用了黑色。

ColorLabel元件的定義,繼承自QLabel,并儲存自己的樣式:

// ColorLabel 使用QSS顯示彩色文字type ColorLabel struct {	widgets.QLabel 	// color style sheet	defaultColor string}           

接着是構造函數,函數的功能在注釋中寫的比較清楚了,關鍵在于它調用的兩個方法:

// NewColorLabelWithColor 生成colorlabel,設定default color為color// color為空則設定為黑色// color可以是顔色對應的名字,例如"black", "green"// 也可以是16進制的RGB值,例如 #ffffff, #ff08ff, #000000func NewColorLabelWithColor(text, color string) *ColorLabel {	l := NewColorLabel(nil, 0) 	l.SetDefaultColor(color)	l.SetDefaultColorText(text) 	return l}           

SetDefaultColor用于給ColorLabel設定預設的顔色,而SetDefaultColorText則和setText槽一樣,給label設定文字,并使用預設指定的顔色顯示,通過這兩個方法我們可以處理絕大部分的使用場景,現在來看看它們的實作:

// SetDefaultColor 設定defaultColor// color為""時設定為黑色// 不會改變現有text内容的顔色func (l *ColorLabel) SetDefaultColor(color string) {	if color == "" {		l.defaultColor = defaultStyle		return	} 	l.defaultColor = fmt.Sprintf(colorStyle, color)} // SetDefaultColorText 設定新的text值,并使其顯示設定的default colorfunc (l *ColorLabel) SetDefaultColorText(text string) {	l.SetText(text)	l.SetStyleSheet(l.defaultColor)}           

當color為空字元串時使用預設顔色,否則設定為color指定的顔色,color可以是顔色的名字/16進制值。值得一提的是,修改預設顔色并不會影響已經顯示的文字,如果想改變已經顯示的文字的顔色,需要使用ChangeColor。

SetDefaultColorText則先使用SetText設定文字,随後添加QSS,因為這中間間隔相當短是以先添加QSS還是後添加不會有明顯可見的差別,而且事件循環也會盡量将兩次調用産生的重繪事件合并。

有時候我們也需要中途修改ColorLabel的顔色,或者顔色和文字一起修改,這時上面的方法就滿足不了我們了,比如在這段代碼裡。

是以我們也實作了這些功能:

// ChangeColor 改變現有text的顔色// 并且設定defaultColor為新的顔色// color為""時設定為defaultStylefunc (l *ColorLabel) ChangeColor(color string) {	l.SetDefaultColor(color)	text := l.Text()	l.SetDefaultColorText(text)} // SetColorText 用color顯示新的text// color為""時顯示defaultStylefunc (l *ColorLabel) SetColorText(text, color string) {	var style string	if color == "" {		style = defaultStyle	} else {		style = fmt.Sprintf(colorStyle, color)	} 	l.SetText(text)	l.SetStyleSheet(style)}           

ChangeColor改變了已顯示文字的顔色,并設定label預設的顔色為新的顔色。SetColorText則顯示指定顔色的文字,不會影響label的預設設定。

有了這些方法,我們就能友善地設定文字的顔色了,而且因為我們繼承自QLabel,是以可以使用QLabel提供的方法對文字的顯示做更進一步的控制。

Qt開發必備技術棧學習路線和資料

Qt資料領取→「連結」