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.cppblog.com/gaimor/
"
));
setting.setValue(
"
maker
"
,QVariant(
"
Gaimor
"
));
setting.endGroup();
这个例子是把数据写到配置文件config.ini中去
当然也可以使用分组的方式写入,具体如下:
setting
.setValue
(
"config/page"
,
QVariant
(
3
));
setting.setValue("config/site",QVariant("http://www.cppblog.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();
}
重新风格项代理
QStyledItemDelegat
class
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);
}