QTableWidget要調整表格行寬主要涉及以下一個函數
1.resizeColumnsToContents
(); 根據內容調整列寬
2.resizeColumnToContents(int col); 根據內容自動調整給定列寬
3.horizontalHeader
()->setResizeMode
把給定列設置為給定模式
主要模式有Stretch和Fixed
QSetting類是QT中專門用于讀寫程序數據的對象
一個簡單的使用例子如下:
QSettings setting("config.ini",QSettings::IniFormat);
setting.beginGroup("config");
setting.setValue("page",QVariant(3));
setting.setValue("site",QVariant("http://www.shnenglu.com/gaimor/"));
setting.setValue("maker",QVariant("Gaimor"));
setting.endGroup();
這個例子是把數據寫到配置文件config.ini中去
當然也可以使用分組的方式寫入,具體如下:
setting
.setValue
("config/page",QVariant(3)); setting.setValue("config/site",QVariant("http://www.shnenglu.com/gaimor/"));
setting.setValue("config/maker",QVariant("Gaimor"));
它的讀寫值得函數原型如下:
void setValue(const QString &key, const QVariant &value);
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
當然QSetting還有其他使用方式,以后慢慢總結
QTableWidget動態增加行的方法
其實很簡單的:
首先rowCount()得到當前中的行數,然后在調用insertRow
(row
);即可
如果要動態增加列,方法類似
QT中 .pro文件的寫法如下:
1. 注釋
從“#”開始,到這一行結束。
2. 指定源文件
SOURCES = *.cpp
對于多源文件,可用空格分開,如:SOURCES = 1.cpp 2.cpp3.cpp
或者每一個文件可以被列在一個分開的行里面,通過反斜線另起一行,就像這樣:
SOURCES = hello.cpp \
main.cpp
還有一種是這樣
SOURCES+= hello.cpp
SOURCES +=main.cpp
這種方法中使用“+=”比“=”更安全,因為它只是向已有的列表中添加新的文件,而不是替換整個列表。
3. 指定頭文件
HEADERS = hello.h或者HEADERS += hello.h
列出源文件的任何一個方法對頭文件也都適用。
4. 配置信息
CONFIG用來告訴qmake關于應用程序的配置信息。
CONFIG+= qt warn_on release
在這里使用“+=”,是因為我們添加我們的配置選項到任何一個已經存在中。這樣做比使用“=”那樣替換已經指定的所有選項是更安全的。
A> qt部分告訴qmake這個應用程序是使用Qt來連編的。這也就是說qmake在連接和為編譯添加所需的包含路徑的時候會考慮到Qt庫的。
B> warn_on部分告訴qmake要把編譯器設置為輸出警告信息的。
C> release部分告訴qmake應用程序必須被連編為一個發布的應用程序。在開發過程中,程序員也可以使用debug來替換release
5. 指定目標文件名
TARGET = filename
如果不設置該項目,目標名會被自動設置為跟項目文件一樣的名稱
6. 添加界面文件(ui)
INTERFACES = filename.ui
7. 平臺相關性處理
我們在這里需要做的是根據qmake所運行的平臺來使用相應的作用域來進行處理。為Windows平臺添加的依賴平臺的文件的簡單的作用域看起來就像這樣:
win32 {
SOURCES += hello_win.cpp
}
所以如果qmake運行在Windows上的時候,它就會把hello_win.cpp添加到源文件列表中。如果qmake運行在其它平臺上的時候,它會很簡單地把這部分忽略。
8. 如果一個文件不存在,停止qmake
如果某一個文件不存在的 時候,你也許不想生成一個Makefile。我們可以通過使用exists()函數來檢查一個文件是否存在。我們可以通過使用error()函數把正在運 行的qmake停下來。這和作用域的工作方式一樣。只要很簡單地用這個函數來替換作用域條件。對main.cpp文件的檢查就像這樣:
!exists( main.cpp ) {
error( "No main.cpp file found")
}
“!”用來否定這個測試,比如,如果文件存在,exists( main.cpp)是真,如果文件不存在,!exists( main.cpp )是真。
9. 檢查多于一個的條件
假設你使用Windows并且當你在命令 行運行你的應用程序的時候你想能夠看到qDebug()語句。除非你在連編你的程序的時候使用console設置,你不會看到輸出。我們可以很容易地把 console添加到CONFIG行中,這樣在Windows下,Makefile就會有這個設置。但是如果告訴你我們只是想在當我們的應用程序運行在 Windows下并且當debug已經在CONFIG行中的時候,添加console。這需要兩個嵌套的作用域;只要生成一個作用域,然后在它里面再生成 另一個。把設置放在最里面的作用域里,就像這樣:
win32 {
debug {
CONFIG += console
}
}
嵌套的作用域可以使用冒號連接起來,像這樣:
win32:debug {
CONFIG += console
}
10. 摸板
模板變量告訴qmake為這個應用程序生成哪種makefile。下面是可供使用的選擇:
A> app -建立一個應用程序的makefile。這是默認值,所以如果模板沒有被指定,這個將被使用。
B> lib - 建立一個庫的makefile。
C> vcapp - 建立一個應用程序的VisualStudio項目文件。
D> vclib - 建立一個庫的VisualStudio項目文件。
E> subdirs -這是一個特殊的模板,它可以創建一個能夠進入特定目錄并且為一個項目文件生成makefile并且為它調用make的makefile。
11. 生成Makefile
當你已經創建好你的項目文件,生成Makefile就很容易了,你所要做的就是先到你所生成的項目文件那里然后輸入:
Makefile可以像這樣由“.pro”文件生成:
qmake -oMakefile hello.pro
對于VisualStudio的用戶,qmake也可以生成“.dsp”文件,例如:
qmake -tvcapp -o hello.dsp hello.pro
使用Delegate具體如下:
class QLineDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
QLineDelegate(QTableView* tableView);
protected:
void paint(QPainter* painter,const QStyleOptionViewItem& option,const QModelIndex& index) const;
bool editorEvent(QEvent *event,
QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index) ;
private:
QPen pen;
QTableView* view;
};
static QRect CheckBoxRect(const QStyleOptionViewItem &view_item_style_options)
{
QStyleOptionButton check_box_style_option;
QRect check_box_rect = QApplication::style()->subElementRect(
QStyle::SE_CheckBoxIndicator,
&check_box_style_option);
QPoint check_box_point(view_item_style_options.rect.x() +
view_item_style_options.rect.width() / 2 -
check_box_rect.width() / 2,
view_item_style_options.rect.y() +
view_item_style_options.rect.height() / 2 -
check_box_rect.height() / 2);
return QRect(check_box_point, check_box_rect.size());
}
QLineDelegate::QLineDelegate(QTableView* tableView)
{
int gridHint = tableView->style()->styleHint(QStyle::SH_Table_GridLineColor, new QStyleOptionViewItemV4());
QColor gridColor = static_cast<QRgb>(gridHint);
pen = QPen(gridColor,0,tableView->gridStyle());
view = tableView;
}
void QLineDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,const QModelIndex& index)const
{
bool checked = index.model()->data(index, Qt::DisplayRole).toBool();
if(index.column() == 0)
{
QStyleOptionButton check_box_style_option;
check_box_style_option.state |= QStyle::State_Enabled;
if(checked)
{
check_box_style_option.state |= QStyle::State_On;
}
else
{
check_box_style_option.state |= QStyle::State_Off;
}
check_box_style_option.rect = CheckBoxRect(option);
QApplication::style()->drawControl(QStyle::CE_CheckBox,&check_box_style_option,painter);
}
QStyledItemDelegate::paint(painter,option,index);
QStyleOptionViewItem itemOption(option);
if(itemOption.state & QStyle::State_HasFocus)
itemOption.state = itemOption.state ^ QStyle::State_HasFocus;
QStyledItemDelegate::paint(painter,itemOption,index);
QPen oldPen = painter->pen();
painter->setPen(pen);
painter->drawLine(option.rect.topRight(),option.rect.bottomRight());
painter->drawLine(itemOption.rect.bottomLeft(),itemOption.rect.bottomRight());
painter->setPen(oldPen);
}
bool QLineDelegate::editorEvent(QEvent *event,
QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index) {
if((event->type() == QEvent::MouseButtonRelease) ||
(event->type() == QEvent::MouseButtonDblClick))
{
QMouseEvent *mouse_event = static_cast<QMouseEvent*>(event);
if(mouse_event->button() != Qt::LeftButton ||
!CheckBoxRect(option).contains(mouse_event->pos()))
{
return false;
}
if(event->type() == QEvent::MouseButtonDblClick)
{
return true;
}
}
else if(event->type() == QEvent::KeyPress)
{
if(static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space &&
static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
{
return false;
}
}
else
{
return false;
}
bool checked = index.model()->data(index, Qt::DisplayRole).toBool();
return model->setData(index, !checked, Qt::EditRole);
}
不過有一個小問題,就是CheckBox旁邊有false/true字符
#include <QtGui>
class ItemDelegate : public QItemDelegate
{
public:
ItemDelegate(QObject *parent = 0)
: QItemDelegate(parent)
{
}
virtual void drawCheck(QPainter *painter, const QStyleOptionViewItem &option,
const QRect &, Qt::CheckState state)const
{
const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
QRect checkRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
check(option, option.rect, Qt::Checked).size(),
QRect(option.rect.x() + textMargin, option.rect.y(),
option.rect.width() - (textMargin * 2), option.rect.height()));
QItemDelegate::drawCheck(painter, option, checkRect, state);
}
virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
const QModelIndex &index)
{
Q_ASSERT(event);
Q_ASSERT(model);
Qt::ItemFlags flags = model->flags(index);
if(!(flags & Qt::ItemIsUserCheckable) || !(flags & Qt::ItemIsEnabled))
return false;
QVariant value = index.data(Qt::CheckStateRole);
if(!value.isValid())
return false;
if(event->type() == QEvent::MouseButtonRelease)
{
const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
QRect checkRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
check(option, option.rect, Qt::Checked).size(),
QRect(option.rect.x() + textMargin, option.rect.y(),
option.rect.width() - (2 * textMargin), option.rect.height()));
if (!checkRect.contains(static_cast<QMouseEvent*>(event)->pos()))
return false;
}
else if(event->type() == QEvent::KeyPress)
{
if(static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space
&& static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
return false;
}
else
{
return false;
}
Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
? Qt::Unchecked : Qt::Checked);
//! 
return model->setData(index, state, Qt::CheckStateRole);
}
void drawFocus(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect) const
{
QItemDelegate::drawFocus(painter, option, option.rect);
}
};
static int ROWS = 3;
static int COLS = 3;
class Table : public QTableWidget
{
public:
Table(QWidget *parent = 0)
: QTableWidget(ROWS, COLS, parent)
{
setItemDelegate(new ItemDelegate(this));
QTableWidgetItem *item = 0;
for(int i=0; i<rowCount(); ++i)
{
for(int j=0; j<columnCount(); ++j)
{
setItem(i, j, item = new QTableWidgetItem);
QTableViewItem;
item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsUserCheckable);
item->setCheckState((i+j) % 2 == 0 ? Qt::Checked : Qt::Unchecked);
}
}
}
};
int main(int argc, char **argv)
{
QApplication a(argc, argv);
Table w;
w.show();
return a.exec();
}
重新風格項代理
QStyledItemDelegatclass QLineDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
QLineDelegate(QTableView* tableView);
protected:
void paint(QPainter* painter,const QStyleOptionViewItem& option,const QModelIndex& index) const;
private:
QPen pen;
QTableView* view;
};
#include <QPainter>
#include "QLineDelegate.h"
QLineDelegate::QLineDelegate(QTableView* tableView)
{
int gridHint = tableView->style()->styleHint(QStyle::SH_Table_GridLineColor, new QStyleOptionViewItemV4());
QColor gridColor = static_cast<QRgb>(gridHint);
pen = QPen(gridColor, 0, tableView->gridStyle());
view = tableView;
}
void QLineDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,const QModelIndex& index)const
{
QStyleOptionViewItem itemOption(option);
if(itemOption.state & QStyle::State_HasFocus)
itemOption.state = itemOption.state ^ QStyle::State_HasFocus;
QStyledItemDelegate::paint(painter,itemOption,index);
QPen oldPen = painter->pen();
painter->setPen(pen);
//painter->drawLine(option.rect.topRight(),option.rect.bottomRight());
painter->drawLine(itemOption.rect.bottomLeft(),itemOption.rect.bottomRight());
painter->setPen(oldPen);
}
默認QTableView是顯示網狀格子的,如果不顯示網格則可以調用setShowGrid
(false);來實現。但是如果只想顯示橫線則有點復雜了。具體代碼如下:
#include <QApplication> #include <QTableWidget>
#include <QPainter>
#include <QStyledItemDelegate>
#include <QHeaderView>
class QLineDelegate : public QStyledItemDelegate
{
public:
QLineDelegate(QTableView* tableView);
protected:
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
private:
QPen pen;
QTableView* view;
};
QLineDelegate::QLineDelegate(QTableView* tableView)
{
int gridHint = tableView->style()->styleHint(QStyle::SH_Table_GridLineColor, new QStyleOptionViewItemV4());
QColor gridColor = static_cast<QRgb>(gridHint);
pen = QPen(gridColor, 0, tableView->gridStyle());
view = tableView;
}
void QLineDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,const QModelIndex& index)const
{
QStyledItemDelegate::paint(painter, option, index);
QPen oldPen = painter->pen();
painter->setPen(pen);
//painter->drawLine(option.rect.topRight(), option.rect.bottomRight());
painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
painter->setPen(oldPen);
}
class QLineTableWidget:public QTableWidget
{
public:
QLineTableWidget();
};
QLineTableWidget::QLineTableWidget()
{
setStyleSheet("QTableView::Item{selection-background-color:#101020}");
setStyleSheet("QTableView::Item{background-color:#F0F0F0}");
verticalHeader()->setVisible(false);
horizontalHeader()->setVisible(true);
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::SingleSelection);
setEditTriggers(QTableView::NoEditTriggers);
setColumnCount(3);
setRowCount(4);
setShowGrid(false);
setItemDelegate(new QLineDelegate(this));
setCurrentCell(-1,-1);
}
int main(int argc,char **argv)
{
QApplication a(argc,argv);
QLineTableWidget widget;
widget.show();
return a.exec();
}
#ifndef QPLUGIN_SYSTEM_H
#define QPLUGIN_SYSTEM_H
#include <QObject>
#include <QVector>
#include <QPluginLoader>
#include <QDir>
template<class T>
class QPluginSystem
{
public:
void setup();
int getAddonCnt(){return addons.size();}
T* getAddonByIndex(int index){return addons.at(index);}
private:
QVector<QPluginLoader*> loaders;
QVector<T*> addons;
};
template<class T>
void QPluginSystem<T>::setup()
{
QString path = QDir::currentPath();
path += QDir::separator();
path += "addons";
QDir pluginsDir(path);
foreach(QString fileName,pluginsDir.entryList(QDir::Files))
{
bool autodel = false;
QPluginLoader* pluginLoader = new QPluginLoader(pluginsDir.absoluteFilePath(fileName));
QObject *plugin = pluginLoader->instance();
if(plugin)
{
T *interface = qobject_cast<T*>(plugin);
if(interface)
{
addons.push_back(interface);
loaders.push_back(pluginLoader);
autodel = true;
}
}
if(autodel == false)
delete pluginLoader;
}
}
#endif
其中T是插件對象,需要繼承QObject
另外雖然我沒試過,但是我感覺增加QPluginLoader鏈表是很有必要的
QT附帶的例子比較好:
class HttpWindow : public QDialog
{
Q_OBJECT
public:
HttpWindow(QWidget *parent = 0);
void startRequest(QUrl url);
private slots:
void downloadFile();
void cancelDownload();
void httpFinished();
void httpReadyRead();
void updateDataReadProgress(qint64 bytesRead, qint64 totalBytes);
void enableDownloadButton();
void slotAuthenticationRequired(QNetworkReply*,QAuthenticator *);
private:
QLabel *statusLabel;
QLabel *urlLabel;
QLineEdit *urlLineEdit;
QProgressDialog *progressDialog;
QPushButton *downloadButton;
QPushButton *quitButton;
QDialogButtonBox *buttonBox;
QUrl url;
QNetworkAccessManager qnam;
QNetworkReply *reply;
QFile *file;
int httpGetId;
bool httpRequestAborted;
};
其中槽有:
1.開始下載
2.取消下載
3.預備下載
4.下載完成
5.進度回調
等
實現為:
void HttpWindow::startRequest(QUrl url)
{
reply = qnam.get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()),
this, SLOT(httpFinished()));
connect(reply, SIGNAL(readyRead()),
this, SLOT(httpReadyRead()));
connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(updateDataReadProgress(qint64,qint64)));
}
該函數主要針對給定url綁定事件
void HttpWindow::downloadFile()
{
url = urlLineEdit->text();
QFileInfo fileInfo(url.path());
QString fileName = fileInfo.fileName();
fileName = "downloadfile.dat";
if(fileName.isEmpty())
fileName = "index.html";
if(QFile::exists(fileName)) {
if (QMessageBox::question(this, tr("HTTP"),
tr("There already exists a file called %1 in "
"the current directory. Overwrite?").arg(fileName),
QMessageBox::Yes|QMessageBox::No, QMessageBox::No)
== QMessageBox::No)
return;
QFile::remove(fileName);
}
file = new QFile(fileName);
if (!file->open(QIODevice::WriteOnly)) {
QMessageBox::information(this, tr("HTTP"),
tr("Unable to save the file %1: %2.")
.arg(fileName).arg(file->errorString()));
delete file;
file = 0;
return;
}
progressDialog->setWindowTitle(tr("HTTP"));
progressDialog->setLabelText(tr("Downloading %1.").arg(fileName));
downloadButton->setEnabled(false);
// schedule the request
httpRequestAborted = false;
startRequest(url);
}
當點擊下載的時候,會執行該函數
獲取url鏈接,生成本地文件,...
void HttpWindow::cancelDownload()
{
statusLabel->setText(tr("Download canceled."));
httpRequestAborted = true;
reply->abort();
downloadButton->setEnabled(true);
}
終止下載,主要函數是reply->abort();
void HttpWindow::httpFinished()
{
if (httpRequestAborted) {
if (file) {
file->close();
file->remove();
delete file;
file = 0;
}
reply->deleteLater();
progressDialog->hide();
return;
}
progressDialog->hide();
file->flush();
file->close();
QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (reply->error()) {
file->remove();
QMessageBox::information(this, tr("HTTP"),
tr("Download failed: %1.")
.arg(reply->errorString()));
downloadButton->setEnabled(true);
} else if (!redirectionTarget.isNull()) {
QUrl newUrl = url.resolved(redirectionTarget.toUrl());
if (QMessageBox::question(this, tr("HTTP"),
tr("Redirect to %1 ?").arg(newUrl.toString()),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
url = newUrl;
reply->deleteLater();
file->open(QIODevice::WriteOnly);
file->resize(0);
startRequest(url);
return;
}
} else {
QString fileName = QFileInfo(QUrl(urlLineEdit->text()).path()).fileName();
statusLabel->setText(tr("Downloaded %1 to current directory.").arg(fileName));
downloadButton->setEnabled(true);
}
reply->deleteLater();
reply = 0;
delete file;
file = 0;
}
下載結束動作
void HttpWindow::httpReadyRead()
{
// this slot gets called every time the QNetworkReply has new data.
// We read all of its new data and write it into the file.
// That way we use less RAM than when reading it at the finished()
// signal of the QNetworkReply
if (file)
file->write(reply->readAll());
}
寫文件回調
void HttpWindow::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
if (httpRequestAborted)
return;
progressDialog->setMaximum(totalBytes);
progressDialog->setValue(bytesRead);
}
進度回調
要點:
1.針對QNetReply綁定需要的信號和槽
2.實現需要的槽函數