1. 程式人生 > >Qt學習之路_12(簡易資料管理系統)

Qt學習之路_12(簡易資料管理系統)

前言

  最近從大陸來到臺灣,之間雜事很多,擠不出時間來更新部落格…

  這次主要是通過做一個簡易的資料庫管理系統,來學習在Qt中對資料庫,xml,介面的各種操作,進一步熟悉Qt。一般而言資料通常存在檔案,資料庫,xml中,本文主要是介紹了sqlite,xml這2種儲存資料的方法,實現了一個家用電器產品的銷售小軟體。參考資料為 http://www.yafeilinux.com/ 程式碼基本也是作者yafei的,我只是看懂一些程式碼然後手動敲入加稍微修改而已。反正以學習他人的程式碼來進一步掌握Qt程式設計。

  實驗過程

  該實驗分為3個部分,商品管理,銷售統計,和修改密碼。

  商品管理:

  在程式執行時,已經建立了商品銷售的資料庫,該資料庫分為3個表,品牌表,分類表,密碼錶。分類表中有2個產品類別,為電視和空調。品牌表中對應的電視有4個品牌,空調有2個品牌,這2者初始化時已經有了庫存資訊,即商品的單價,剩餘商品的數量等。密碼錶中設定了初始化密碼,初始密碼為”2012”。 與此同時也建立xml來儲存資料,裡面有日銷售清單,還設定了銷售日期,時間,品牌的資訊,供後面銷售完畢後來進行查詢和儲存。

  在商品管理頁,選擇對應的品牌,型別,和打算賣出的數量,則軟體會自動計算賣出的總額和剩餘對應產品的數量。單擊售出的確認按鈕後,右邊的頁面會顯示銷售的記錄,其中的資訊包括銷售時間,日期,品牌的數量,價格等等。

  銷售統計:

  銷售統計這一欄用表格和餅圖來顯示銷售產品數量的分佈情況。可以在銷售統計右側的下拉列框中選擇電視和空調2個型別中的一個,然後左側的表格會顯示品牌和銷售數量2個量,品牌左側有不同顏色的小方框顯示。右側顯示的是其對應的餅圖,餅圖旁邊有小方框顯示不同顏色代表不同的銷售商品。在左邊的表格中單擊表格單元格,可以看到右邊餅圖對應的那一個扇形的顏色更改了。銷售統計中顯示錶格和餅圖需要重寫QAbstractItemView類中的很多函式,其中不少函式沒有自己去敲程式碼,直接賦值過來的。

  密碼更改:

  在密碼更改頁中,可以修改登入密碼,新密碼需要2遍確認,這些操作都與普通的更改密碼操作類似。修改後的密碼會被儲存在sqlite資料庫中。

  實驗說明

  介面設計時的小技巧:

  1.如果把控制元件放在佈局檔案中,那麼該控制元件自身的尺寸和控制元件之間的幾何量會被自動改變,因為這些都是交給了佈局檔案來管理。那麼怎麼做到將設計好了的控制元件放入佈局檔案後不改變這些幾何變數呢?首先,如果需要固定控制元件之間的距離量,可以加入彈簧;其實,如果需要固定控制元件的幾何尺寸,可以在Qt Designer中控制元件的屬性欄的minimumSize和maximumSize兩個欄中都設定為同樣大小。這樣即使控制元件放入佈局檔案中,也不會更改它們本身的幾何量了。

  2. 如果需要把各控制元件按照自己的習慣排布好,而這時不打算使用佈局檔案(因為佈局檔案會自動改變控制元件的大小),這時可以採用一個Stack Widget,讓其它的控制元件任意形狀放入其中。

  3. 分割器並不單單指的中間一條分割線,而是指的包括分割線2側的widget,即可以理解為一個矩形,它也有長和寬。

  資料庫中的一些小知識:

  資料庫的一些語法中,有些地方需要加單引號,這個不能漏。

  PRIMARY KEY 約束唯一標識資料庫表中的每條記錄;主鍵必須包含唯一的值;主鍵列不能包含 NULL 值;每個表都應該有一個主鍵;並且每個表只能有一個主鍵。

  QSqlQuery這個類是用來查詢sql資料庫的類;QSqlDatabase是用來建立資料庫的類;

  事務操作是使用者定義的一個數據庫操作序列,這些操作要麼全做要麼全不做,是一個不可分割的操作。在Qt中事務操作時以transaction()開始的,以commit()函式或者rollback()函式進行結束的。這兩者的區別是commit()表示提交,即把事務中所有對資料庫的更新寫到資料庫,事務是正常結束的。Rollback()表示回滾,即如果事務執行過程中發生了某些故障,事務不能繼續進行,則系統將事務中對資料庫的所有已完成的操作全部撤銷,回滾到事務開始的狀態。

  QSqlDatabase::database()返回前面成功連線的QSqlDatabase物件。

  XML使用小知識點:

  對XML文件的操作有2種方法:DOM和SAX。其中DOM是把XML文件轉換成應用程式可以遍歷的樹形結構,這樣便可以隨機訪問其中的節點。缺點是需要把整個XML文件讀入記憶體,這樣消耗記憶體會很大。

  tagName 屬性返回被選元素的標籤名。

  這次實驗通過程式碼來建立一個xml檔案,主要是用到了QDomDocument這個類中的很多方法,xml檔案有點類似樹形結構,本次實驗最初始建立的xml檔案內容截圖如下:

  

  Qt使用一些小知識點:

  QString::number(num)可以將整型的num轉換成string型。

  qreal 其實就是double型。

  往QListWidget加入文字可以使用其addItem()方法.

  arg()中的引數是QString型,則其對應的百分號需要用單引號括起來。

  Qt::DecorationRole是Qt::ItemDataRole中的一種, Qt::ItemDataRole表示每一個model中的Item都有自己的一個數據集,且有自己的特色。這些特點用來指定模型中的哪一種資料型別將被使用。而Qt::DecorationRole指的是說資料將以圖表的形式來呈現。

  QAbstractItemView為一個抽象item檢視類,裡面有很多方法可以重寫。

  QPaint是一個繪圖類,可以設定畫筆,畫刷,字型。

  在設計使用者名稱密碼登陸時,如果使用者名稱和密碼都正確,則會呼叫呼叫父類的QDialog::accept()槽函式,該函式實現關閉當前對話方塊,設定對話方塊的執行結果為QDialog::Accepted,併發送QDialog::finished(int result)訊號。

  增加StackWidget頁面的方法,在StackWidget上滑鼠右擊,選擇insert page,然後繼續選擇在本頁之前或者之後加入頁碼。

  商品管理中的出售商品一欄:    

  通過將產品的型別,品牌,價格,數量,金額等資訊寫入xml檔案,各種資訊都以一個時間為標籤,做為該標籤下面的各子標籤。

  實驗結果:

  登入介面如下:

  

  商品管理功能如下:

  

  銷售統計功能如下:

  

  密碼修改介面如下:

  

  實驗主要部分程式碼及註釋(附錄有工程code下載連結):

connection.h:

複製程式碼
#ifndef CONNECTION_H
#define CONNECTION_H

#include <QtSql>
#include <QDebug>
#include <QtXml>

//該標頭檔案就一個函式,即建立關聯表的函式
static bool createConnection()
{
    //SqlDatabase為實現資料庫連線的類
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");//建立一個數據庫,新增資料庫驅動
    db.setHostName("tornadomeet");
    db.setDatabaseName("data.db");//設定資料庫的名字
    db.setUserName("tornadomeet1");//設定資料庫的使用者名稱
//    db.setPassword("2012");//設定資料庫的密碼
    if(!db.open())
        return false;

    QSqlQuery query;//新建一個查詢庫

    //建立一個型別表,表名為type;varchar是用來儲存可變長度的字串
    query.exec("create table type(id varchar primary key, name varchar)");
    query.exec(QString("insert into type values('00', '請選擇型別')"));//表中的第一個項
    query.exec(QString("insert into type values('01', '電視')"));//加入第二項
    query.exec(QString("insert into type values('02', '空調')"));//第三項

    //建立一個品牌表,表名為brand
    query.exec("create table brand(id varchar primary key, name varchar, "
               "type varchar, price int, sum int, sell int, last int)");
    query.exec(QString("insert into brand values('01', '海信', '電視', '3699', '50', '10', '40')"));
    query.exec(QString("insert into brand values('02', '創維', '電視', '3499', '20', '5', '15')"));
    query.exec(QString("insert into brand values('03', '海爾', '電視', '4199', '80', '40', '40')"));
    query.exec(QString("insert into brand values('04', '王牌', '電視', '3999', '40', '10', '30')"));
    query.exec(QString("insert into brand values('05', '海爾', '空調', '2699', '60', '10', '50')"));
    query.exec(QString("insert into brand values('06', '格力', '空調', '2799', '70', '20', '50')"));
//    query.exec("insert into type brand('05', '海爾', '空調', '2699', '60', '10', '50')");
//    query.exec("insert into type brand('06', '格力', '空調', '2799', '70', '20', '50')");
    query.exec("create table password(pwd varchar primary key)");
    query.exec("insert into password values('2012')");

    return true;
}

static bool createXml()
{
    QFile file("data.xml");//建立一個xml檔案
    if(file.exists())
        return true;
    if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))//以只寫方式開啟,且清零以前的資訊
        return false;
    QDomDocument doc;//新建一個QDomDocument類物件,它代表一個xml檔案
    QDomProcessingInstruction instruction;//新增處理指令
    instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild(instruction);//xml檔案版本等資訊
    QDomElement root = doc.createElement(QString("目錄銷售清單"));
    doc.appendChild(root);//增加根目錄
    QTextStream out(&file);//指定文字流
    doc.save(out, 4);//將xml文件儲存到檔案data.xml檔案中,4表示子元素縮排字元數
    file.close();

    return true;
}

#endif // CONNECTION_H
複製程式碼

datamanager.h:

複製程式碼
#ifndef DATAMANAGER_H
#define DATAMANAGER_H

#include <QMainWindow>
#include <QDomDocument>

namespace Ui {
class DataManager;
}

class QStandardItemModel;//這個類為Qt中提供了儲存定製資料的通用模型

class DataManager : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit DataManager(QWidget *parent = 0);
    ~DataManager();

    enum DataTimeType{Time, Date, DateTime};//定義時間的列舉型別
    QString getDataTime(DataTimeType type);
    
private slots:
    void on_sellTypeComboBox_currentIndexChanged(const QString &arg1);

    void on_sellBrandComboBox_currentIndexChanged(const QString &arg1);

    void on_sellNumSpinBox_valueChanged(int arg1);

    void on_sellCancelButton_clicked();

    void on_sellOkButton_clicked();

    void on_typeComboBox_currentIndexChanged(const QString &arg1);

    void on_updateButton_clicked();

    void on_manageButton_clicked();

    void on_chartButton_clicked();

    void on_passwordButton_clicked();

    void on_okButton_clicked();

    void on_cancelButton_clicked();

private:
    Ui::DataManager *ui;

    QDomDocument doc;
    QStandardItemModel *chartModel;
    bool docRead();
    bool docWrite();
    void writeXml();
    void createNodes(QDomElement &data);
    void showDailyList();

    void createChartModelView();
    void showChart();
};

#endif // DATAMANAGER_H
複製程式碼

datamanager.cpp:

複製程式碼
#include "datamanager.h"
#include "ui_datamanager.h"
#include "connection.h"
#include "pieview.h"
#include <QtSql>
#include <QtXml>
#include <QtGui>

DataManager::DataManager(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::DataManager)
{
    ui->setupUi(this);
    ui->stackedWidget->setCurrentIndex(0);
    QSqlQueryModel *typeModel = new QSqlQueryModel(this);//新建一個Sql查詢模組
    typeModel->setQuery(QString("select name from type"));//執行改句相當於執行查詢語句,其結果可以設定在組合框中
    ui->sellTypeComboBox->setModel(typeModel);

    QSplitter *splitter = new QSplitter(ui->managePage);//增加一個分隔符
    splitter->resize(680, 400);
    splitter->move(10, 40);
    splitter->addWidget(ui->toolBox);
    splitter->addWidget(ui->dailyList);
    splitter->setStretchFactor(0, 1);//第一個widget的分割器中所佔面積大小之比為1
    splitter->setStretchFactor(1, 1);

    on_sellCancelButton_clicked();//初始化各控制元件的狀態
    showDailyList();

    ui->typeComboBox->setModel(typeModel);
    createChartModelView();

}

DataManager::~DataManager()
{
    delete ui;
}

void DataManager::on_sellTypeComboBox_currentIndexChanged(const QString &arg1)
{
    if(arg1 == "請選擇型別")
        {;}
    else
    {
        ui->sellBrandComboBox->setEnabled(true);
        QSqlQueryModel *model = new QSqlQueryModel(this);
        model->setQuery(QString("select name from brand where type = '%1'").arg(arg1));//注意單引號是英文狀態下的
        ui->sellBrandComboBox->setModel(model);
        ui->sellCancelButton->setEnabled(true);//取消按鈕可用
    }
}

void DataManager::on_sellBrandComboBox_currentIndexChanged(const QString &arg1)
{
    ui->sellNumSpinBox->setValue(0);//將數量值設定為0
    ui->sellNumSpinBox->setEnabled(false);//數量值那一欄不可更改
    ui->sellSumLineEdit->clear();//金額數清0
    ui->sellSumLineEdit->setEnabled(false);//金額一欄不可用
    ui->sellOkButton->setEnabled(false);//確定按鈕也不可用

    QSqlQuery query;
    query.exec(QString("select price from brand where name ='%1' and type ='%2'").
               arg(arg1).arg(ui->sellTypeComboBox->currentText()));
    query.next();//查詢記錄指向相鄰的下一條記錄
    ui->sellPriceLineEdit->setEnabled(true);//單價輸入框
    ui->sellPriceLineEdit->setReadOnly(true);
    ui->sellPriceLineEdit->setText(query.value(0).toString());//value(0)為獲得第0個屬性的值,這裡指的是price

    query.exec(QString("select last from brand where name ='%1' and type = '%2'").
               arg(arg1).arg(ui->sellTypeComboBox->currentText()));
    query.next();//移向第一個記錄
    int num = query.value(0).toInt();//取出來
    if(0 == num)
    {
        QMessageBox::information(this, tr("提示"), tr("該商品已經銷售完了!"), QMessageBox::Ok);
    }
    else
    {
        ui->sellNumSpinBox->setEnabled(true);//可用使用
        ui->sellNumSpinBox->setMaximum(num);//設定最大值為剩餘數量的值
        ui->sellLastNumLabel->setText(tr("剩餘數量: %1").arg(num));
        ui->sellLastNumLabel->setVisible(true);//其實預設情況下就是可見的
    }


}

void DataManager::on_sellNumSpinBox_valueChanged(int arg1)
{
    if(arg1 == 0)
    {
        ui->sellSumLineEdit->clear();//清零且不可用
        ui->sellSumLineEdit->setEnabled(false);
        ui->sellOkButton->setEnabled(false);
    }
    else
    {
        ui->sellSumLineEdit->setEnabled(true);
        ui->sellSumLineEdit->setReadOnly(true);
        //qreal其實就是一個double型
        qreal sum = arg1*(ui->sellPriceLineEdit->text().toInt());//賣出的數量*單價等於總額
        ui->sellSumLineEdit->setText(QString::number(sum));//顯示總額
        ui->sellOkButton->setEnabled(true);
    }
}

void DataManager::on_sellCancelButton_clicked()
{
    ui->sellTypeComboBox->setCurrentIndex(0);

    ui->sellBrandComboBox->clear();//品牌框不可用,且清零
    ui->sellBrandComboBox->setEnabled(false);

    ui->sellPriceLineEdit->clear();
    ui->sellPriceLineEdit->setEnabled(false);//單價欄不可用

    ui->sellNumSpinBox->setValue(0);//數量欄清零且不可用
    ui->sellNumSpinBox->setEnabled(false);

    ui->sellSumLineEdit->clear();
    ui->sellSumLineEdit->setEnabled(false);//總額欄不可用

    ui->sellOkButton->setEnabled(false);
    ui->sellCancelButton->setEnabled(false);//按鈕不可用
    ui->sellLastNumLabel->setVisible(false);//剩餘數不可見
}

void DataManager::on_sellOkButton_clicked()
{
    //QSqlDatabase::database()返回前面成功連線的QSqlDatabase物件。
    QString type = ui->sellTypeComboBox->currentText();
    QString name = ui->sellBrandComboBox->currentText();
    int value = ui->sellNumSpinBox->value();//當前打算賣出的量
    int last = ui->sellNumSpinBox->maximum()-value;//當前還剩餘的量
    QSqlQuery query;
    query.exec(QString("select sell from brand where name=%1 and type=2%").arg(name).arg(type));
    query.next();//指向結果集的第一條記錄
    int sell = query.value(0).toInt()+value;//總共售出量
    QSqlDatabase::database().transaction();//事務操作開始
    bool rtn = query.exec(QString("update brand set sell=%1, last=%2 where name='%3' and type='%4'").arg(sell).
                          arg(last).arg(name).arg(type));
    if(rtn)
    {
        QSqlDatabase::database().commit();//上面查詢操作成功時,則提交事務操作
        QMessageBox::information(this, tr("提示"), tr("購買成功!"), QMessageBox::Ok);
        writeXml();
        showDailyList();
        on_sellCancelButton_clicked();
  //      qDebug() << "It's OK!";
    }
    else
    {
        QSqlDatabase::database().rollback();//如果上述查詢操作失敗,則執行事務回滾
    }
}


QString DataManager::getDataTime(DataManager::DataTimeType type)
{
    QDateTime datetime = QDateTime::currentDateTime();
    QString date = datetime.toString("yyyy-MM-dd");
    QString time = datetime.toString("hh:mm");
    QString date_time = datetime.toString("yyyy-MM-dd dddd hh:mm");
    if(type == Date)
        return date;
    else if(type == Time)
        return time;
    else return date_time;
}


//將xml檔案中的內容讀取到QDomDocument類物件中去
bool DataManager::docRead()
{
    QFile file("data.xml");
    if(!file.open(QIODevice::ReadOnly))//開啟檔案
    {
        return false;
    }
    if(!doc.setContent(&file))//讀取檔案
    {
        file.close();
        return false;
    }
    file.close();
    return true;
}


//將QDomDocument類物件的內容寫到xml文件中去
bool DataManager::docWrite()
{
    QFile file("data.xml");
    if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
        return false;
    QTextStream out(&file);
    doc.save(out, 4);//將doc內容存入到file中
    file.close();
    return true;
}

void DataManager::writeXml()
{
    if(docRead())
    {
        QString currentDate = getDataTime(Date);//獲得當前日期
        QDomElement root = doc.documentElement();//獲得當前文件根節點
        if(!root.hasChildNodes())
        {
            QDomElement date = doc.createElement(QString("日期"));//增加一個標籤
            QDomAttr curDate = doc.createAttribute("date");//增加一個屬性
            curDate.setValue(currentDate);//給屬性賦值
            date.setAttributeNode(curDate);//
            
           

相關推薦

Qt學習_12(簡易資料管理系統)

前言   最近從大陸來到臺灣,之間雜事很多,擠不出時間來更新部落格…   這次主要是通過做一個簡易的資料庫管理系統,來學習在Qt中對資料庫,xml,介面的各種操作,進一步熟悉Qt。一般而言資料通常存在檔案,資料庫,xml中,本文主要是介紹了sqlite,xml這2種儲存資料的方法,實現了一個家用電器產

Qt學習_11(簡易多文件編輯器)

前言:   本文將介紹怎樣用Qt做一個簡單的多文件編輯器,該實驗的過程中主要涉及到Qt視窗的設計,選單欄(包括右擊選單),工具欄,狀態列,常見的文字檔案等操作。參考資料為網址上的一個例子:http://www.yafeilinux.com/   本來是在ubuntu下做這個實驗的,可是一開始建立選單欄等時,

QT學習資料部落格:《Qt 實戰一二三》和《Qt 學習 2》等

參考原貼 https://blog.csdn.net/dpsying/article/details/80615320 目的:僅供自己學習,並無他用。 參考書目: 1《Qt5開發及例項》(Qt 5.8為平臺)         

QT學習十六(QWebView實現簡易瀏覽器)

QtWebkit 模組介紹   QtWebkit 模組提供了一個在Qt中使用web browser的engine,這使得我們在QT的應用程式中使用全球資訊網上的內容變得很容易,而且對其網頁內容的控制也可以通過native controls 實現  。   QtWebkit具

Qt學習-簡易畫板5(完成)

昨天做出了滑鼠拖動的雛形,以為可以完美的加到原來的程式上結果發現直接用QPainterPath簡單更多,於是今天就重新寫了份,也是遇到很多問題最後慢慢解決了,在以前的功能上新增了滑鼠選定拖動的功能,並且拖動時有痕跡,效果如下: 程式碼提供下載,類設計的不好,但是很適

Qt 學習 2(40):隱式數據共享

深拷貝和淺拷貝 != 這樣的 pointer map painter pos 轉載 多線程 博客轉載自:https://www.devbean.net/2013/01/qt-study-road-2-implicit-sharing/ Qt 中許多 C++ 類使用了隱式數據

Qt 學習 2(42):QListWidget、QTreeWidget 和 QTableWidget

上一章我們瞭解了 model/view 架構的基本概念。現在我們從最簡單的QListWidget、QTreeWidget和QTableWidget三個類開始瞭解最簡單的 model/view 的使用。這部分內容的確很難組織。首先,從最標準的 model/view 開始,往往會糾結於複雜的程式碼;但是

0.0 開啟自己的QT學習

2008年左右接觸過一段時間的QT,感覺到了QT的方便快捷,之前我是做JAVA的,不過C++也還能看得懂,一共用QT開發了3個月左右的時間,一直是公司的同事帶著做。N年過去了,QT忘得差不多了,QT也有了很大的發展,現在重新學習是為了之後的工作。 打算用一個周的時間學完QT,達到能開發和看懂QT

QT學習---訊號與槽問題解析

前兩天用到了QT的訊號與槽這個機制,剛開始發射訊號的時候,我是這麼寫的語句 connect(sender,SINGAL(),receiver,SLOT()) 由於我用的是QT 5.11這個本,從網上查到的例子來說,大部分都是以上那個形式,也沒有問題,而實際上在QT5.11版本上,向下面這樣寫

MySQL學習——五(資料操作)

                                                   資料操作 一、增     1.指定欄位        命令:insert into 表名 (欄位1,欄位2,……) values (值1,值2,……);    

weifu的qt學習

1、寫入文字檔案 使用文字檔案輸出的步驟:         1)包含標頭檔案fstream         2)建立一個ofstream物件         3)將該ofstream物件同一個檔案關聯起來。 關聯的方法:ofstream物件.open("文字檔名")

資料學習111-大資料專案(中國移動運營資料分析)

業務一: 業務二: 統計每個省份的充值失敗資料量,並以地圖的方式顯示分佈情況。 資料說明: 充值的整個過程是包括: 訂單建立->支付請求->支付通知->充值請求->充值通知 而我們需要處理的就是充值通知部分的資料。而我們的資料中是包

Qt 學習之路 2(19):事件的接受與忽略(當重寫事件回撥函式時,時刻注意是否需要通過呼叫父類的同名函式來確保原有實現仍能進行!有好幾個例子。為什麼要這麼做?而不是自己去手動呼叫這兩個函式呢?因為我們無法確認父類中的這個處理函式有沒有額外的操作)

版本: 2012-09-29 2013-04-23 更新有關accept()和ignore()函式的相關內容。 2013-12-02 增加有關accept()和ignore()函式的示例。 上一章我們介紹了有關事件的相關內容。我們曾經提到,事件可以依情況接受和忽略。現在,我們就

mybatis學習----批量更新資料兩種方法效率對比

點滴記載,點滴進步,願自己更上一層樓。 上節探討了批量新增資料,這節探討批量更新資料兩種寫法的效率問題。 實現方式有兩種, 一種用for迴圈通過迴圈傳過來的引數集合,迴圈出N條sql, 另一種 用mysql的case when 條件判斷變相的進行批量更新   下面進行實現

Qt 學習---安裝篇】QT5.7.1+VS2013軟體開發環境配置

參考:https://blog.csdn.net/liushuiwen101423/article/details/70882534 安裝任務:完成Qt5.7.1載入到VS2013環境下,程式設計執行Qt應用程式,有詳細步驟,最後完成一個空白視窗UI執行顯示1.基本配置PC

QT學習(8):事件的傳遞和忽略

事件有兩個函式,accept()和event(),前者代表該元件希望接受這個事件,這個事件將不會傳播.而後者代表該元件希望忽略這個事件那麼事件就會繼續向它的父元件傳播.所有事件都是預設為accept()的,但是在QWidget中的所有事件回撥函式都是呼叫了ign

Qt 學習 2(26):反走樣

我們在光柵圖形顯示器上繪製非水平、非垂直的直線或多邊形邊界時,或多或少會呈現鋸齒狀外觀。這是因為直線和多邊形的邊界是連續的,而光柵則是由離散的點組成。在光柵顯示裝置上表現直線、多邊形等,必須在離散位置取樣。由於取樣不充分重建後造成的資訊失真,就叫走樣;用於減少或消除這種效

OpenCV學習(附加資料分享)

目錄 一、前言 二、學習歷程 三、學習資料 書籍 網站 視訊教程 四、學習建議 入門 強化 靈通 一、前言 有人問我,學習opencv從哪裡學起?有人問我,我學習opencv用到了哪些資料?所以在今天,我要先給大家分享一下我的opencv之路。

Qt學習自定義按鈕

按鈕有三種狀態:當滑鼠點選的時候,當滑鼠進入按鈕的時候,當滑鼠沒有進入按鈕的時候,這3個不同的狀態。 上程式碼~~~~ pushBtn_widget.h  /* 貼圖按鈕的狀態: 進入, 離開, 按下 */ #ifndef PUSHBTNWIDGET_H #def

QT學習計算器開發

前幾天老師簡單的講解了下QT的訊號與槽,並且實現了一個簡單的計算機加法,如下圖: 我根據對老師所講類容的理解以及一些資料的查詢自己做了一個簡單的計算器。 1 首先上個介面,頁面佈局用Grid Layout。 2 建立各種槽,程式碼如下: mainwindow.h檔案程