整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Qt繪圖

          Qt繪圖

          .QPainter

          • 2D繪圖離不開QPainter,可以把QPainter想象成一個畫筆,開發人員拿著畫筆理論上是可以繪制任何 你想要的圖形。QPainter 一般在一個部件(widget)重繪事件(PaintEvent )的處理函數paintEvent () 中進行繪制,首先要創建QPainter 對象(畫筆),然后進行圖形的繪制

          1.1常用函數

                  drawArc() 弧 
                  drawChord() 弦 
                  drawConvexPolygon() 凸多邊形 
                  drawEllipse() 橢圓,注意橢圓是先整個框,然后逼近
                  drawImage() 圖像 
                  drawLine() 線 
                  drawLines() 多條線 
                  drawPath()路徑; 想到哪就去哪,但是必須是直的 
                  drawPicture() 按QPainter指令繪制 區分drawImage、drawPixmap 
                  drawPie() 扇形 
                  drawPixmap() 圖像 
                  drawPoint() 點 
                  drawPoints() 多個點
                  drawPolygon()多邊形 
                  drawPolyline() 多折線 
                  drawRect() 矩形 
                  drawRects() 多個矩形
                  drawRoundRect() 圓角矩形 
                  drawText() 文字 
                  drawTiledPixmap() 平鋪圖像
                  drawLineSegments() 繪制折線
          

          1.2畫圖和畫刷

          • QPen和QBrush

          1.3paintEvent什么時候調用

          //1、窗口隱藏和顯示
          //2、出窗口大小改變
          //3、調用update()
          //4、調用repaint()
          

          Qt資料領取→「鏈接」

          么是扁平化

          這里的扁平化指的是交互設計方面的一種風格。

          扁平化是隨著極簡注意的風潮流行起來的,這個概念最核心的地方就是放棄一切裝飾效果,諸如陰影。透視,紋理,漸變等等能做出3D效果的元素一概不用。全部的元素的邊界都干凈利落,沒有不論什么羽化。漸變,或者陰影。從比較早的windows 8的Metro,

          windows8

          ios

          android

          都后面Android4.0的Holo Style,還有iOS7的“Ivy style” 的扁平化設計。

          【領QT開發教程學習資料,點擊下方鏈接免費領取↓↓,先碼住不迷路~】

          點擊→領取「鏈接」

          那之后,感覺一切都被拍扁了。

          今天從技術的角度來看看怎么讓Qt程序扁平化。

          終于的效果是這種(一個圖片瀏覽器)

          扁平化。走你!

          自己定義扁扁的按鈕

          QWidget w;
          w.show().

          上面的代碼會生成一個Qt的Widget,然后顯示出來,這種窗體會帶上系統自帶的外框,也包括有最大化,最小化之類的按鈕,可是這種按鈕并非我們須要的style,并且我們也無法控制,所以我們須要自己實現右上角的窗體控制按鈕,創建一個pushbutton類,繼承自QPushButton。

          pushbutton.h

          #ifndef PUSHBUTTON_H
          #define PUSHBUTTON_H
          
          #include <QPushButton>
          #include <QMouseEvent>
          #include <QPainter>
          #include <QDebug>
          
          class PushButton : public QPushButton
          {
          	Q_OBJECT
          
          public:
          	PushButton(QWidget *parent=0);
          	~PushButton();
          	void loadPixmap(QString pic_name);
          
          protected:
          	void enterEvent(QEvent *);
          	void leaveEvent(QEvent *);
          	void mousePressEvent(QMouseEvent *event);
          	void mouseReleaseEvent(QMouseEvent *event);
          	void paintEvent(QPaintEvent *);
          
          private:
          	enum ButtonStatus{NORMAL, ENTER, PRESS, NOSTATUS};
          	ButtonStatus status;
          	QPixmap pixmap;
          
          	int btn_width;
          	int btn_height;
          	bool isPressed;
          };
          
          #endif // PUSHBUTTON_H
          

          【領QT開發教程學習資料,點擊下方鏈接免費領取↓↓,先碼住不迷路~】

          點擊→領取「鏈接」
          pushbutton.cpp

          #include "pushbutton.h"
          
          PushButton::PushButton(QWidget *parent)
          	:QPushButton(parent)
          {
          	status=NORMAL;
          	isPressed=false;
          }
          
          PushButton::~PushButton()
          {
          
          }
          
          void PushButton::loadPixmap(QString pic_name)
          {
          	pixmap.load(pic_name);
          	//QSize picSize(96, 32);
          	pixmap=pixmap.scaledToHeight(30);
          	btn_width=pixmap.width()/3;
          	btn_height=pixmap.height();
          	setMinimumSize(btn_width, btn_height);
          }
          
          void PushButton::enterEvent(QEvent *)
          {
          	status=ENTER;
          	update();
          }
          
          void PushButton::mousePressEvent(QMouseEvent *event)  
          {  
          	if (event->button()==Qt::LeftButton)  
          	{
          		isPressed=true;
          		status=PRESS;
          		update();
          	}
          }
          
          void PushButton::mouseReleaseEvent(QMouseEvent *)
          {
          	if(isPressed)
          	{
          		isPressed=false;
          		status=ENTER;
          		update();
          		emit clicked();
          	}
          }
          
          void PushButton::leaveEvent(QEvent *)
          {
          	status=NORMAL;
          	update();
          }
          
          void PushButton::paintEvent(QPaintEvent *)
          {
          	QPainter painter(this);
          	painter.drawPixmap(rect(), pixmap.copy(btn_width * status, 0, btn_width, btn_height));
          }


          須要準備一張button的圖片。包括button的各個狀態,依據button不同的狀態在paintEvent函數中繪制圖片不同的部分。


          去除邊框加上widget投影

          去除系統自帶的邊框僅僅須要一行代碼就能夠了。

          setWindowFlags(Qt::FramelessWindowHint);


          給widget加入投影的方法卡了我兩天。網上現存的有兩種方法,一種是先準備好一些陰影的圖片,然后手動在paintEvent中把陰影一個部分一個部分畫出來。

          這個方案費時費力,不靈活,效果也不太好。

          還有一種方法是stackoverflow上的,加入一個widget,把全部窗體控件放到這個widget中,給這個widget加入陰影效果,然后放在一個透明的widget上。這個我試了非常久,效果也不太好。

          最后給出我的解決方法.

          自己定義widget繼承自QWidget,構造函數中

          	this->setWindowFlags(Qt::FramelessWindowHint);
          	this->setAttribute(Qt::WA_TranslucentBackground);

          用一個layout裝下全部控件,然后

          #define SHADOW_WIDT 5

          mainLayout->setContentsMargins(SHADOW_WIDTH, SHADOW_WIDTH, SHADOW_WIDTH, SHADOW_WIDTH);
          this->setLayout(mainLayout);


          在main.cpp中

          	MainWindow w;   
          	QGraphicsDropShadowEffect *wndShadow=new QGraphicsDropShadowEffect;
          	wndShadow->setBlurRadius(5.0);
          	wndShadow->setOffset(0);
          	wndShadow->setColor(QColor("#017acc"));
          	w.setGraphicsEffect(wndShadow);
          	w.show();  


          效果還算完美^.

          設置widget背景

          兩種方法。第一。使用QPalette

          m_pMyWidget=new QWidget(this);
          m_pMyWidget->setGeometry(0,0,300,100);
          QPalette Pal(palette());
          // set black background
          Pal.setColor(QPalette::Background, Qt::black);
          m_pMyWidget->setAutoFillBackground(true);
          m_pMyWidget->setPalette(Pal);
          m_pMyWidget->show();


          另外一種,使用css

          m_pMyWidget=new QWidget(this);
          m_pMyWidget->setGeometry(0,0,300,100);
          m_pMyWidget->setStyleSheet("background-color:black;");
          m_pMyWidget->show();


          就像用css來修飾Html一樣,css也能夠用來定義widget的樣式,Qt中使用樣式表的文檔能夠參考這里和這里。

          注。不論什么自己定義繼承子QWidget的Widget,想要使用樣式表,都要手動實現paintevent函數,代碼例如以下:

          void CustomWidget::paintEvent(QPaintEvent *)
           {
               QStyleOption opt;
               opt.init(this);
               QPainter p(this);
               style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
           }

          小結

          相比于使用Qt自帶的窗體管理,自己定義的扁平化窗體看上肯定高大上很多。但隨之而來的是開發成本和設計成本,由于全部的widget如今都須要自己管理(大小,顏色等),所以在開發之前一定要做好權衡。

          21. 在對表格數據模型操作的時候,經常遇到一種場景就是,刪除某條記錄后,希望重新選中某一行。QTableView、QTableWidget本身就支持多選全選等操作,比如批量刪除可以多選。

          //拿到表格數據模型
          QAbstractItemModel *model=ui->tableView->model();
          //主動定位到第三行
          ui->tableView->setCurrentIndex(model->index(3, 0));
          //主動定位到最后一行
          ui->tableView->setCurrentIndex(model->index(model->rowCount() - 1, 0));
          
          //設置選擇模式支持多選,其他幾個枚舉值自行查閱文檔。
          ui->tableView->setSelectionMode(QAbstractItemView::MultiSelection);
          
          //選擇全部
          ui->tableView->selectAll();
          //取消所有選中
          ui->tableView->clearSelection();
          
          //選中行,注意如果該行選中則執行后取消選中,如此往復。這個設計很巧妙,掌聲。
          ui->tableView->selectRow(row);
          //選中列,注意如果該列選中則執行后取消選中,如此往復。這個設計很巧妙,掌聲。
          ui->tableView->selectColumn(column);
          
          //獲取選中行的內容
          QItemSelectionModel *selections=ui->tableView->selectionModel();
          QModelIndexList selected=selections->selectedIndexes();
          foreach (QModelIndex index, selected) {
              qDebug() << index.row() << index.column() << index.data();   
          }

          222. 在讀取文本文件的時候,有時候會發現讀取出來的中文亂碼,這個時候就需要識別文件編碼格式,然后主動設置對應的編碼去讀取就不會亂碼。

          //檢查文件編碼 0=ANSI 1=UTF-16LE 2=UTF-16BE 3=UTF-8 4=UTF-8BOM
          int DataCsv::findCode(const QString &fileName)
          {
              //假定默認編碼utf8
              int code=3;
              QFile file(fileName);
              if (file.open(QIODevice::ReadOnly)) {
                  //讀取3字節用于判斷
                  QByteArray buffer=file.read(3);
                  quint8 b1=buffer.at(0);
                  quint8 b2=buffer.at(1);
                  quint8 b3=buffer.at(2);
                  if (b1==0xFF && b2==0xFE) {
                      code=1;
                  } else if (b1==0xFE && b2==0xFF) {
                      code=2;
                  } else if (b1==0xEF && b2==0xBB && b3==0xBF) {
                      code=4;
                  } else {
                      //嘗試用utf8轉換,如果可用字符數大于0,則表示是ansi編碼
                      QTextCodec::ConverterState state;
                      QTextCodec *codec=QTextCodec::codecForName("utf-8");
                      codec->toUnicode(buffer.constData(), buffer.size(), &state);
                      if (state.invalidChars > 0) {
                          code=0;
                      }
                  }
          
                  file.close();
              }
          
              return code;
          }

          223. 在連接遠程數據庫進行查詢數據的時候,有時候會發現很慢,尤其是表數據量越多越慢,本地的話同等數據量快很多,可以嘗試開啟只前進屬性,query.setForwardOnly(true);這樣的話只會緩存一次的數據,大大提高遠程數據庫的查詢效率,據說可以提高幾十倍百倍的速度。當然前提是對查詢的數據之前向前取數據的需求,如果還要往后取數據或者在數據模型QSqlQueryModel中使用,則不能開啟此屬性。原因在每次利用QSqlQuery獲取下一條記錄時,若不開啟isForwardOnly屬性(很遺憾默認就是不開啟),則每次都開辟新的內存空間,來存儲已經訪問及未訪問的記錄,這樣,每次都會浪費好多存儲空間。

          224. Qt中的painter繪制非常靈活強大,接口豐富,但是對于很多初學者來說還是有一定的難度,尤其是各種奇奇怪怪的復雜格式,而這些格式用html確很好描述,比如控制行間距、字符間距等,此時可以用QTextDocument傳入html格式內容交給QPainter繪制,非常完美、簡單、強大,包括一些數學公式啥的。

          void Form::paintEvent(QPaintEvent *event)
          {
              QPainter painter(this);
              QTextDocument doc;
              doc.setHtml(html);
              //設置文本寬度
              doc.setTextWidth(200);
              //指定繪制區域
              doc.drawContents(&painter, QRect(0, 0, 200, 70));
          }

          225. Qt中樣式表對選中顏色和懸停顏色是有優先級的,根據對操作系統默認樣式的觀察,當處于選中狀態+懸停狀態的時候,默認取懸停狀態,也就是鼠標移動到選中的列表item上,顏色取懸停狀態顏色。而Qt中如果兩種顏色都設置了,根據設置的順序來,取最后的為準,如果最后設置的選中狀態顏色,則當item處于選中狀態+懸停狀態的時候,取選中狀態顏色而不是懸停狀態顏色,切記!


          主站蜘蛛池模板: 亚洲片一区二区三区| 97久久精品无码一区二区| 性色AV 一区二区三区| 亚洲福利视频一区二区| 无码国产精品一区二区免费3p| 国产成人精品一区二区三在线观看| 亚洲AV美女一区二区三区| 国产成人综合精品一区| 波多野结衣一区二区三区88| 欧美日韩综合一区二区三区| 国产精品一区在线麻豆| 波多野结衣一区二区| 国产福利91精品一区二区| 亚洲一区二区三区在线| 色欲AV蜜臀一区二区三区| 久久精品国产第一区二区三区| 日韩一区二区电影| 日韩精品一区二区三区中文 | 无码少妇一区二区三区芒果| 一区二区三区日韩| 亚洲午夜精品一区二区公牛电影院| 无码人妻一区二区三区免费n鬼沢 无码人妻一区二区三区免费看 | 亚洲AV无码一区二区一二区| 亚洲综合av一区二区三区不卡| 无码人妻一区二区三区免费手机| 国产一区在线mmai| 成人在线观看一区| 视频在线观看一区| 日韩精品无码一区二区视频| 久久久精品日本一区二区三区| 一区二区三区免费在线视频| 国产一区二区视频在线播放| 国产午夜三级一区二区三| 久久国产一区二区三区| 久久一区二区三区免费播放| 中文字幕视频一区| 国产成人欧美一区二区三区| 视频一区视频二区制服丝袜| 麻豆一区二区三区蜜桃免费| 久久婷婷色综合一区二区| 国模吧一区二区三区|