11.3 通用对话框:QColorDialog、QFontDialog、QInputDialog

本节介绍通用对话框:QColorDialog、QFontDialog、QInputDialog,并通过示例程序展示这三种对话框的使用。

11.3.1 QColorDialog

在介绍 QColorDialog 之前,我们先简单介绍一下 QColor 类。QColor 类用于表示颜色,支持 RGB(红绿蓝)三原色表示,也支持其他颜色模型表示,例如 HSV (hue 色调, saturation 饱和度, value 明亮度),CMYK(cyan 青, magenta 紫或叫品红, yellow 黄,  black 黑)。HSV 常用于描述人眼对颜色的感官,CMYK 常用于绘画或彩色印刷的颜料配置。计算机显示则更多地使用 RGB 三原色,下面我们主要介绍 RGB 的颜色模型相关函数内容。
针对半透明显示的特效,颜色也可以使用第四个分量,Alpha 通道,表示半透明程度,与三原色一起就是 ARGB。QColor 对象的构造或修改如下:
QColor(int r, int g, int b, int a = 255)  //根据红、绿、蓝、Alpha构造颜色对象
void    setRgb(int r, int g, int b, int a = 255) //设置红、绿、蓝、Alpha 值
int    red() const      //获取红色分量
int    green() const  //获取绿色分量
int    blue() const    //获取蓝色分量
int    alpha() const  //获取Alpha分量
void    getRgb(int * r, int * g, int * b, int * a = 0) const  //一次性读取四个通道值到参数指针指向的变量

颜色除了数值的表示方法,还可以仿照 HTML/CSS 网页中的颜色表述,比如 RGB 使用字符串表示 "#112233" ,这里是十六进制字符串表示,ARGB 表示为  "#ff112233" ,字符串表述的颜色设置和获取函数如下:
QString QColor::​name() const   //获取字符串表示的颜色,如 "#RRGGBB"
void QColor::​setNamedColor(const QString & name)  //设置字符串表示的颜色,如 "#RRGGBB"

QColor 对象如果初始化时没有设置任何颜色,那么处于不合法状态,可以使用下面函数判断:
bool QColor::​isValid() const
如果颜色合法,返回 true ,如果不合法,返回 false。

下面介绍 QColorDialog 对话框,QColorDialog 用于获取颜色,比如标签控件的前景色、背景色等,都可以通过 QColorDialog 获取颜色,然后修改界面控件的配色。QColorDialog 获取的颜色使用 QColor 对象返回。QColorDialog 颜色对话框如下图所示:
color1
对话框左上角是基本颜色的网格,点击颜色网格可以获取基本颜色,右边则是大片的渐变颜色区域,渐变颜色区域每一个点都是一种颜色。对话框左下角可以添 加自定义的新 颜色到网格中,方便下次选取。右下角的 Red、Green、Blue 三色编辑框也可以修改颜色分量的值。HTML 编辑框内容就是当前颜色对应网页字符串的颜色描述方式。
颜色对话框有两种使用方式,一种是自定义对话框对象进行弹窗,第二种是使用对话框的静态函数弹窗。第二种静态函数的使用方式更为便捷。
(1)QColorDialog 普通成员函数
颜色对话框继承基类 QDialog 所有的函数,可以模态显示,也可以非模态显示,exec()、show() 等函数与基类一样。
颜色对话框的构造和析构函数如下:
QColorDialog(QWidget * parent = 0)
QColorDialog(const QColor & initial, QWidget * parent = 0)
~QColorDialog()
第一个构造函数参数只是设置父窗口指针,第二个构造函数可以指定一个初始颜色值,在弹窗时默认选中这个颜色。
颜色对话框获取颜色的普通成员函数分两种场景,第一种场景是在对话框保持显示时,用户点击的颜色:
QColor    currentColor() const   //获取当前颜色
void    setCurrentColor(const QColor & color)   //设置当前颜色
void    currentColorChanged(const QColor & color)  //信号,当前颜色变化时触发该信号
如果是非模态显示的自定义颜色对话框,那么使用上面函数可以随时获取用户点选颜色的变化。

第二种场景获取颜色的普通函数,是需要用户点击“OK”按钮确认后,最终返回的颜色:
QColor    selectedColor() const   //用户选择颜色并且点击 “OK”确认后返回的颜色值
void    colorSelected(const QColor & color) //信号,用户选择颜色并且点击 “OK”确认后,触发该信号
用户点击“OK”按钮后对话框就自动关闭了,selectedColor() 是最终选择的颜色,而前面的 currentColor() 可以一直变化选择。

QColorDialog 重载了基类的打开函数:
void QColorDialog::​open(QObject * receiver, const char * member)
这个打开函数参数里第一个 receiver 是接收 colorSelected() 信号的对象,第二个 member 就是一次性关联的槽函数名称。这个 open() 函数是一次性的,如果关闭了,那么 receiver 对象 member  槽函数会自动解绑。

QColorDialog 还可以设置特殊的颜色对话框选项:
ColorDialogOptions    options() const  //获取颜色对话框选项
void    setOptions(ColorDialogOptions options)   //设置颜色对话框选项
void    setOption(ColorDialogOption option, bool on = true)  //开启或禁用一个选项标志位
bool    testOption(ColorDialogOption option) const  //测试一个选项标志位是否为 true
具体的 ColorDialogOptions  枚举常量如下:

QColorDialog::ColorDialogOptions 枚举常量 数值 描述
QColorDialog::ShowAlphaChannel 0x00000001 允许用户选择颜色的 Alpha 分量。
QColorDialog::NoButtons 0x00000002 不显示“OK”和“Cancel”按钮(用于长期显示的非模态对话框)。
QColorDialog::DontUseNativeDialog 0x00000004 使用 Qt 风格标准颜色对话框,而不使用操作系统本土风格颜色对话框。

这些 ColorDialogOptions 都是二进制标志位,默认情况都是 0 ,除了有特殊需求情况,一般不使用这些标志位。
以上普通成员函数都是自定义对话框对象使用,实际中使用下面的静态函数模态显示更为方便。

(2)QColorDialog 静态成员函数
颜色对话框的静态函数就是针对静态函数内部临时定义的对话框对象,每次都是模态弹出:
QColor    getColor(const QColor & initial = Qt::white, QWidget * parent = 0, const QString & title = QString(), ColorDialogOptions options = 0)   //静态函数
静态函数 getColor() 参数里,initial 是初始选中的颜色,parent 是父窗口指针,title 是颜色对话框的标题文本,options 就是上面表格中的 ColorDialogOptions 标志位设置。
使用简单的一个函数就能获取一个颜色,这是非常方便使用的,例如:
QColor clr = QColorDialog::getColor();
这样一句简单代码就可以获取到颜色值。
注意 QColorDialog::getColor() 对话框显示时,如果用户按下 Cancel 按钮或者 Esc 键,那么会返回非法值的颜色对象,所以要注意判断返回值是否合法。
静态函数弹出的颜色对话框也可以进行一定的定制小操作,例如上面图片颜色对话框的左上角基本颜色网格,也叫 StandardColor ,可以进行修改:
QColor    standardColor(int index)   //静态函数,根据序号获取标准颜色(基本颜色)
void    setStandardColor(int index, QColor color)  //静态函数,根据序号设置标准颜色(基本颜色)
标准颜色网格或叫基本颜色网格,根据序号可以获取对应网格的颜色,也能修改网格颜色。
颜色对话框左下角的是 CustomColor ,就是用户定制颜色,初始时是空白的,用户选择某个颜色,点击“Add to Custom Colors ”按钮,就会添加到左下角的用户定制颜色网格。程序员也可以通过代码提前定制几个颜色:
int    customCount()   //静态函数,可以设置的用户定制颜色总数
QColor    customColor(int index)  //静态函数,根据序号获取用户定制颜色
void    setCustomColor(int index, QColor color)  //静态函数,根据序号设置用户定制颜色

11.3.2 QFontDialog

在介绍 QFontDialog 对话框之前,我们先简单介绍一下 QFont 字体类。QFont 主要用于控制文本显示的字体,字体主要有四大属性:
①字体家族 family 决定字体外观家族,比如宋体、楷体等;
②字号 pointSize (磅数)决定字显示的尺寸大小,字号 1 磅等于 1/72 英寸;
③字重 weight 决定字笔画的粗细;
④斜体 italic 决定是否倾斜显示文字。
QFont 构造函数如下:
QFont()
QFont(const QString & family, int pointSize = -1, int weight = -1, bool italic = false)
QFont(const QFont & font, QPaintDevice * pd)
QFont(const QFont & font)
第一个默认构造函数不是构造空白的字体对象,而是根据应用程序默认字体构造新对象,比如宋体9号字体对象。
第二个构造函数四个参数就是字体对象的四大属性。
第三个构造函数是根据 QPaintDevice 对象内部使用的字体复制一个相同的字体对象。
第四个构造函数是复制构造参数里的字体对象。
四大属性相对应的函数如下表所示:

读取函数 设置函数 描述
QString family() const void setFamily(const QString & family) 读取和设置字体家族名称,如果字体名不存在,就设置一个相近的字体家族。
int pixelSize() const void setPixelSize(int pixelSize) 字体的像素尺寸,以占据屏幕像素点为参考,与屏幕点阵间距相关,不同屏幕的像素间距不一样。
int pointSize() const void setPointSize(int pointSize) PointSize 是真实尺子上的一磅刻度,1/72英寸距离,72磅就是1英寸。在不同屏幕一磅尺寸一样大。
int weight() const void setWeight(int weight) 字体重量,取值0-99,正常是50,数字越大笔画越粗。
bool italic() const void setItalic(bool enable) 斜体设置,如果为 true 是倾斜显示文字,false 就是正常显示。

针对字体重量,QFont 预设了几个档次的枚举值:

QFont::​Weight枚举常量 数值 描述
QFont::Light 25 轻体笔画。
QFont::Normal 50 正常笔画。
QFont::DemiBold 63 略粗笔画。
QFont::Bold 75 粗体笔画。
QFont::Black 87 黑重笔画。

针对字体重量,还有两个函数,可以判断和设置粗体:
bool    bold() const   // 凡是字体重量大于 QFont::Normal 都返回 true,小于等于 QFont::Normal 返回 false
void    setBold(bool enable)   //当参数为 true 时,设置字体为 QFont::Bold,如果参数 false 就设置为 QFont::Normal
字体类常用的函数介绍到这。下面我们介绍获取字体的 QFontDialog  对话框。

QFontDialog 继承了基类对话框的所有函数,可以进行模态和非模态显示,如 exec() 、show() 函数直接继承自基类。字体对话框外观如下图所示:
font1
对话框中左上角位置是字体家族名称,上部中间是字体风格,包含粗体斜体设置,右上角是字号磅数。对话框左下角是字体效果删除线、下划线,以及书写系统 习惯,比如简 体中文 Simplified Chinese。右下角是当前选中字体显示样例。
QFontDialog 也有两种使用方式,第一种是自定义字体对话框,使用普通成员函数获取字体;第二种是使用静态函数,模态弹窗获取字体。
(1)QFontDialog 普通成员函数
QFontDialog 构造函数如下:
QFontDialog(QWidget * parent = 0)
QFontDialog(const QFont & initial, QWidget * parent = 0)
参数 parent  是父窗口指针,第二个构造函数可以指定初始显示的字体 initial 。
QFontDialog 获取字体的普通函数也分两种场景,一种场景是对话框持续显示时,用户点击选择的字体:
QFont    currentFont() const      //获取当前选中的字体
void    setCurrentFont(const QFont & font)  //设置当前字体
void    currentFontChanged(const QFont & font)  //信号,当前字体变化时触发该信号
对于非模态显示的自定义字体对话框,关联 currentFontChanged() 信号可以实时获取用户点选的字体,并进行同步字体设置。用户只要不停地换字体,currentFontChanged() 就不停地触发,该信号与字体对话框显示都是持续的。
另一种场景是点击“OK”按钮后最终选择的字体:
QFont    selectedFont() const    //点击“OK”按钮后最终选择的字体
void    fontSelected(const QFont & font)  //信号,点击“OK”按钮后触发该信号,参数是最终选择字体
点击“OK”按钮之后,字体对话框会关闭,因此是最终选择的字体。fontSelected() 随着对话框关闭触发,是一次性的。

QFontDialog 重载了基类的打开函数:
void QFontDialog::​open(QObject * receiver, const char * member)
这个打开函数是一次性的,将信号 fontSelected() 关联到 receiver 对象的 member 槽函数上,方便传递最终选择的字体,对话框关闭后,自动解除信号和槽函数绑定,只有一次触发。

QFontDialog 也有对话框选项 FontDialogOption 的设置:
FontDialogOptions    options() const  //获取字体对话框选项
void    setOptions(FontDialogOptions options)  //设置字体对话框选项
void    setOption(FontDialogOption option, bool on = true)  //启用或禁用一个选项标志位
bool    testOption(FontDialogOption option) const  //测试一个选项标志位是否为 true
QFontDialog::​FontDialogOptions 标志位枚举常量如下表所示:

QFontDialog::​ FontDialogOptions 枚举常量 数值 描述
QFontDialog::NoButtons 0x00000001 不显示“OK”和“Cancel”按钮(用于长期显示的非模态对话框)。
QFontDialog::DontUseNativeDialog 0x00000002 使用 Qt 标准风格字体对话框,不使用操作系统本土风格字体对话框。
QFontDialog::ScalableFonts 0x00000004 显示可缩放字体(字号任意可调)。
QFontDialog::NonScalableFonts 0x00000008 显示不可缩放字体(限定一个或几个字号)。
QFontDialog::MonospacedFonts 0x00000010 显示等宽字体。
QFontDialog::ProportionalFonts 0x00000020 显示比例字体(非等宽字体)。

通常都是使用默认的标志位数值 0,有定制需求时才设置上面的标志位。

(2)QFontDialog 静态成员函数
字体对话框提供了两个便捷的获取字体静态函数,模态显示临时的对话框对象:
QFont    getFont(bool * ok, QWidget * parent = 0)
QFont    getFont(bool * ok, const QFont & initial, QWidget * parent = 0, const QString & title = QString(), FontDialogOptions options = 0)
 ok 指针指向表示用户点击对话框“OK”按钮(true)或“Cancel”按钮(false)的状态值;parent 是父窗口指针。
第二个 getFont() 还带有其他参数:初始化的字体 initial,对话框标题 title ,对话框标志位选项 options 。
两个 getFont() 在用户点击“OK”按钮后,返回最终选择的字体;如果用户点击“Cancel”按钮或按 Esc 键,那么第一个 getFont() 返回应用程序默认字体,第二个 getFont() 返回参数里的 initial 字体。
getFont() 返回的字体对象本身总是有效的,用户点击 OK”按钮或“Cancel”按钮的状态就靠 * ok 变量的真假状态来区分。getFont() 静态函数使用示例:
    bool bOK = false;
    QFont font = QFontDialog::getFont( &bOK );
    if( bOK )
    {
        ui->pushButtonFont->setFont(font);
    }
    else
    {
        qDebug()<<"Use the old font.";
    }

Qt 应用程序的默认字体可以进行读取或修改:
QFont QApplication::​font()   //静态函数,获取应用程序默认的字体
void QApplication::​setFont(const QFont & font, const char * className = 0)  //静态函数,设置应用程序默认字体
参数 className  默认是空的,表示字体对程序所有界面类的对象生效;
如果设置了 className  字符串,那么字体仅对 className  类及其派生类对象生效。

11.3.3 QInputDialog

QInputDialog 用于方便快捷地获取一个用户输入数据,支持整数 int、浮点数 double、文本 QString 三种数据。按照 QInputDialog 内部的输入控件,又可以分为整数输入控件 QSpinBox、浮点数输入控件 QDoubleSpinBox、单行文本输入控件 QLineEdit、多行文本输入控件 QPlainTextEdit、组合框输入控件 QComboBox 等。QInputDialog 将这些常见输入控件包装成输入对话框形式,方便获取用户输入。
QInputDialog 可以作为自定义对话框对象使用,也可以使用静态函数直接弹窗获取输入。
QInputDialog 构造函数比较简单:
QInputDialog(QWidget * parent = 0, Qt::WindowFlags flags = 0)
参数里可以指定父窗口指针和窗口标志位。
构建输入对话框之后,可以设置其输入模式:
void    setInputMode(InputMode mode)  //设置整数、浮点数或文本输入模式
InputMode    inputMode() const  //获取当前输入模式
输入模式枚举常量如下表所示:

QInputDialog::​ InputMode 枚举常量 数值 描述
QInputDialog::TextInput 0 用于输入文本字符串。
QInputDialog::IntInput 1 用于输入整数。
QInputDialog::DoubleInput 2 用于输入双精度浮点数。

我们下面按照输入控件的类型分别介绍 QInputDialog 功能,先介绍输入对话框的普通成员函数,最后介绍常用的静态成员函数。
(1)整数输入
QInputDialog 整数输入对话框如下图所示:
int
上图标题栏文本 title 为“设置整数”,对话框带的提示标签 label  为“请输入整数值”,两个按钮显示默认的“OK”和“Cancel”文本。整数使用 QSpinBox 获取整数,可以定制整数取值范围和旋钮步进,相关函数如下 表所示:

整数输入相关函数 描述
int intValue() const 获取整数值。
int intMinimum() const 获取整数值范围下限。
int intMaximum() const 获取整数值范围上限。
int intStep() const 获取旋钮框整数步进。
void setIntValue(int value) 设置整数值。
void setIntMinimum(int min) 设置整数值范围下限。
void setIntMaximum(int max) 设置整数值范围上限。
void setIntStep(int step) 设置旋钮框整数步进。
void setIntRange(int min, int max) 设置整数值范围。

对话框处于显示状态,整数值变化时,触发信号:
void    intValueChanged(int value)
如果用户点击了“OK”按钮,对话框关闭,触发最终选择整数值的信号:
void    intValueSelected(int value)

(2)浮点数输入
QInputDialog 浮点数输入对话框如下图所示:
double
上图标题栏文本 title 为“设置浮点数”,提示标签 label 的文本为“请输入浮点数值:”,浮点数旋钮框的小数点后面只显示了一位。详细的浮点数输入定 制函数如下表所示:

浮点数输入相关函数 描述
double doubleValue() const 获取浮点数值。
double doubleMinimum() const 获取浮点数范围下限。
double doubleMaximum() const 获取浮点数范围上限。
int doubleDecimals() const 获取浮点数小数点后的位数。
void setDoubleValue(double value) 设置浮点数值。
void setDoubleMinimum(double min) 设置浮点数范围下限。
void setDoubleMaximum(double max) 设置浮点数范围上限。
void setDoubleDecimals(int decimals) 设置浮点数小数点后的位数。
void setDoubleRange(double min, double max) 设置浮点数范围。

对话框处于显示状态,浮点数变化时,触发信号:
void    doubleValueChanged(double value)
如果用户点击了“OK”按钮,对话框关闭,触发最终选择浮点数值的信号:
void    doubleValueSelected(double value)

(3)单行文本输入
QInputDialog 单行文本输入对话框如下图所示:
lineedit
用户输入文本后点击“OK”按钮或者按 Enter 键就会返回一行文本 QString;如果用户点击“Cancel”按钮或者按 Esc 键,返回空字符串。单行文本输入相关函数如下:

单行文本输入相关函数 描述
QString textValue() const 获取文本字符串。
QLineEdit::EchoMode textEchoMode() const 获取文本回显模式。
void setTextValue(const QString & text) 设置文本字符串。
void setTextEchoMode(QLineEdit::EchoMode mode) 设置文本回显模式。

文本回显模式就是 QLineEdit::EchoMode 单行编辑器的枚举常量,如下表所示:

QLineEdit::EchoMode 枚举常量 数值 描述
QLineEdit::Normal 0 正常模式,输入什么就显示什么。
QLineEdit::NoEcho 1 无回显模式,用户输入时字符保存在内存中,但是编辑框不显示任何东西,常用于密码输入。
QLineEdit::Password 2 密码回显模式,用 * 或者·代替字符显示。
QLineEdit::PasswordEchoOnEdit 3 密码编辑回显模式,用户输入字符时显示正常字符,其他不输入的时间都用 * 或者·代替字符显示。

对话框处于显示状态,文本变化时,触发信号:
void    textValueChanged(const QString & text)
如果用户点击了“OK”按钮,对话框关闭,触发最终输入文本的信号:
void    textValueSelected(const QString & text)

(4)组合框条目输入
QInputDialog 组合框条目输入对话框如下图所示:
combo
组合框右边可以点击三角形图标,展开条目列表。默认情况组合框内嵌的编辑框是可以直接编辑文本的。组合框条目输入相关函数如下:

整数输入相关函数 描述
QStringList comboBoxItems() const 获取组合框条目列表。
bool isComboBoxEditable() const 判断组合框内嵌编辑框是否可以编辑。
void setComboBoxItems(const QStringList & items) 设置组合框条目列表。
void setComboBoxEditable(bool editable) 设置组合框内嵌编辑框是否可以编辑。

组合框获取的也是文本,所以其触发的信号与单行文本输入时的情况一样,也是 textValueChanged() 和 textValueSelected() 。

(5)其他普通成员函数
输入对话框可以定制提示标签和两个按钮的文本,相关函数如下:
QString    labelText() const   //获取提示标签文本
QString    okButtonText() const   //获取“OK”按钮文本
QString    cancelButtonText() const   //获取“Cancel”按钮文本
void    setLabelText(const QString & text)   //设置提示标签文本
void    setOkButtonText(const QString & text)   //设置“OK”按钮文本
void    setCancelButtonText(const QString & text)   //设置“Cancel”按钮文本

输入对话框也重载了基类的打开函数:
void    open(QObject * receiver, const char * member)
该函数会一次性绑定信号到参数 receiver 对象的 member 槽函数,关联槽函数时,根据槽函数的参数自动判断使用输入对话框对应的信号:
①如果 member 槽函数第一个参数是 QString,将  textValueSelected()  信号关联到槽函数。
②如果 member 槽函数第一个参数是 int,将 intValueSelected() 信号关联到槽函数。
③如果 member 槽函数第一个参数是 double,将 doubleValueSelected() 信号关联到槽函数。
④如果 member 槽函数没有参数,将 accepted() 信号关联到槽函数。
对话框关闭时,自动解除上述信号和槽函数的关联。

输入对话框也有几个选项标志位,相关函数如下:
InputDialogOptions    options() const  //获取对话框选项
void    setOptions(InputDialogOptions options)  //设置对话框选项
void    setOption(InputDialogOption option, bool on = true)  //设置一个选项标志位
bool    testOption(InputDialogOption option) const   //测试一个选项标志位是否为 true
QInputDialog::​InputDialogOptions 标志位枚举常量如下表所示:

QInputDialog::​ InputDialogOptions 枚举常量 数值 描述
QInputDialog::NoButtons 0x00000001 不显示“OK”和“Cancel”按钮(用于长期显示的非模态对话框)。。
QInputDialog::UseListViewForComboBoxItems 0x00000002 使用QListView取代QComboBox进行条目列表的显示。
QInputDialog::UsePlainTextEditForTextInput 0x00000004 使用QPlainTextEdit取代默认单行编辑器实现多行文本输入。

对于 QInputDialog 自定义对话框,如果设置 QInputDialog::TextInput 文本输入模式,那么默认采用单行编辑器输入文本,如果希望输入多行文本,那么还需要将选项标志位 QInputDialog::UsePlainTextEditForTextInput 设为 true,这样才会启用多行编辑器。
静态函数 getMultiLineText() 也会自动设置 QInputDialog::UsePlainTextEditForTextInput 标志位为 true ,启用多行编辑。多行编辑输入对话框如下图所示:
multiline

(6)静态成员函数
QInputDialog 五种输入控件对应五个静态函数:
①获取整数值
int    getInt(QWidget * parent, const QString & title, const QString & label, int value = 0, int min = -2147483647, int max = 2147483647, int step = 1, bool * ok = 0, Qt::WindowFlags flags = 0)
参数里 parent 是父窗口指针,title 为对话框标题栏文本,label 是提示标签的文本,value 是初始值,min 为整数范围下限,max 是整数范围上限,step 是旋钮框的步进,ok 指针用于指向表示点击“OK”或“Cancel”的状态变量,flags 是窗口标志位。

②获取浮点数值
double    getDouble(QWidget * parent, const QString & title, const QString & label, double value = 0, double min = -2147483647, double max = 2147483647, int decimals = 1, bool * ok = 0, Qt::WindowFlags flags = 0)
getDouble() 与 getInt() 类似,只是把步进变量换成了小数点后的位数变量。

③获取单行文本
QString    getText(QWidget * parent, const QString & title, const QString & label, QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(), bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone)
getText() 参数里 mode 是字符回显模式,text 是初始的文本,ok 指针用于指向表示点击“OK”或“Cancel”的状态变量,flags 是窗口标志位变量,inputMethodHints 是输入方式提示,比如密码、时间、数字等输入类型提示。inputMethodHints 特性是从基类 QWidget 继承的,仅仅是提示功能,不会限制任何输入,一般可以忽略。

④获取多行文本
QString    getMultiLineText(QWidget * parent, const QString & title, const QString & label, const QString & text = QString(), bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone)
多行文本使用 QPlainTextEdit 输入多行文本,没有 QLineEdit 控件的回显模式设置,其他参数与 getText() 参数类似。

⑤获取组合框条目文本
QString    getItem(QWidget * parent, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone)
getItem() 也是获取文本,只是用组合框保存多个文本条目,供用户选择或编辑。参数 items 是条目文本列表,current 是默认选中的条目序号,editable 表示组合框内嵌编辑器是否可以编辑文本,其他参数与 getText() 参数类似。

静态函数与自定义对话框使用过程是类似的,只是静态函数更为简洁,以 getMultiLineText() 函数源代码为例:
QString QInputDialog::getMultiLineText(QWidget *parent, const QString &title, const QString &label,
                                       const QString &text, bool *ok, Qt::WindowFlags flags,
                                       Qt::InputMethodHints inputMethodHints)
{
    QInputDialog dialog(parent, flags);
    dialog.setOptions(QInputDialog::UsePlainTextEditForTextInput);
    dialog.setWindowTitle(title);
    dialog.setLabelText(label);
    dialog.setTextValue(text);
    dialog.setInputMethodHints(inputMethodHints);

    int ret = dialog.exec();
    if (ok)
        *ok = !!ret;
    if (ret) {
        return dialog.textValue();
    } else {
        return QString();
    }
}
getMultiLineText() 函数里面定义了临时的输入对话框 dialog;
设置选项标志位QInputDialog::UsePlainTextEditForTextInput,表示使用多行编辑器 QPlainTextEdit ;
设置窗口标题栏、提示标签文本、编辑器初始文本以及窗口输入提示等;
使用 dialog.exec() 模态显示对话框,返回值存到 ret;
根据 ret 设置 ok 指向的变量值,连续两个取反 ! 感叹号,其实就和 ret 真假判断一致,只是把 int 类型转成了 bool 类型;
ret 如果为 true,说明点击了“OK”按钮,返回编辑框文本字符串;
ret 如果为 false,说明点击了“Cancel”按钮,返回空字符串。
我们使用自定义的对话框对象,可以参考上面代码编写,当然也可以改用持续的非模态对话框。

11.3.4 对话框使用示例 CustomizeLabel

下面我们学习一个 CustomizeLabel 示例,使用本节的三种对话框定制修改标签的显示外观。
我们打开 QtCreator,新建一个 Qt Widgets Application 项目,在新建项目的向导里填写:
①项目名称 customizelabel,创建路径 D:\QtProjects\ch11,点击下一步;
②套件选择里面选择全部套件,点击下一步;
③基类选择 QWidget,注意修改主窗口类名为 WidgetCustomizeLabel,然后点击下一步;
④项目管理不修改,点击完成。
由于使用 Qt 通用对话框,就不再需要额外新建自己的子窗口类和UI文件。
我们打开 widgetcustomizelabel.ui 界面文件,拖入控件:
ui1
窗口左边是标签“显示样例”,标签对象名为 labelSample,将标签 sizePolicy 属性的水平策略和垂直策略都修改为的 Expanding;
右边是四个按钮:“设置前景色”按钮 pushButtonForeground,“设置背景色”按钮 pushButtonBackground,“设置字体”按钮 pushButtonFont,“设置文本”按钮 pushButtonText。
右边四个按钮先按照垂直布局器排列,然后选中窗口根 WidgetCustomizeLabel,对窗口整体使用水平布局器排列。窗口尺寸是默认的 400*300 。
然后我们依次右击四个按钮,为每个按钮都添加 clicked() 信号对应的槽函数。
四个按钮槽函数添加完成后,我们保存并关闭  widgetcustomizelabel.ui 界面文件。

下面我们编辑头文件 widgetcustomizelabel.h 内容:
#ifndef WIDGETCUSTOMIZELABEL_H
#define WIDGETCUSTOMIZELABEL_H

#include <QWidget>
#include <QColorDialog>
#include <QFontDialog>
#include <QInputDialog>

namespace Ui {
class WidgetCustomizeLabel;
}

class WidgetCustomizeLabel : public QWidget
{
    Q_OBJECT

public:
    explicit WidgetCustomizeLabel(QWidget *parent = 0);
    ~WidgetCustomizeLabel();

private slots:
    void on_pushButtonForeground_clicked();

    void on_pushButtonBackground_clicked();

    void on_pushButtonFont_clicked();

    void on_pushButtonText_clicked();

    //手动添加槽函数,动态更新前景色
    void RecvAndSetForegroundColor(QColor color);

private:
    Ui::WidgetCustomizeLabel *ui;
    //保存前景色、背景色、字体、输入文本
    QColor m_clrForeground;
    QColor m_clrBackground;
    QFont m_font;
    QString m_strText;
    //单独定制一个前景色对话框
    QColorDialog *m_pDlgForeground;
    //初始化
    void Init();
};

#endif // WIDGETCUSTOMIZELABEL_H
我们添加了颜色对话框、字体对话框和输入对话框的头文件包含;
类声明里面,在四个按钮槽函数之后,手动添加了槽函数  RecvAndSetForegroundColor() 用于接收实时的前景色变化信号,用户在前景色对话框修改颜色时,主界面会实时更新标签前景色。
类里面还添加了保存前景色、背景色、字体和文本的成员,并添加初始化函数 Init() 。

下面我们分段编辑 widgetcustomizelabel.cpp 源文件内容,首先是构造函数和初始化部分:
#include "widgetcustomizelabel.h"
#include "ui_widgetcustomizelabel.h"
#include <QDebug>

WidgetCustomizeLabel::WidgetCustomizeLabel(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::WidgetCustomizeLabel)
{
    ui->setupUi(this);
    //初始化
    Init();
}

//初始化
void WidgetCustomizeLabel::Init()
{
    //背景色浅灰,前景色黑色
    m_clrBackground = QColor(240,240,240);
    m_clrForeground = QColor(0,0,0);
    m_strText = tr("显示样例");
    //新建前景色对话框
    m_pDlgForeground = new QColorDialog(this);
    //隐藏按钮,非模态对话框,保持持续显示
    m_pDlgForeground->setOptions( QColorDialog::NoButtons );
    //关联信号和槽
    connect(m_pDlgForeground, SIGNAL(currentColorChanged(QColor)),
            this, SLOT(RecvAndSetForegroundColor(QColor)) );
}

WidgetCustomizeLabel::~WidgetCustomizeLabel()
{
    delete m_pDlgForeground;    m_pDlgForeground = NULL;
    delete ui;
}
构造函数里添加了 Init() 函数调用。
Init() 函数里面先设置了默认的背景色、前景色和文本字符串;
新建了前景色对话框存到 m_pDlgForeground,
设置前景色对话框的选项 QColorDialog::NoButtons,这样对话框没有“OK”和“Cancel”按钮,会作为非模态窗口持续显示。最后将前景色对话框的 currentColorChanged() 信号关联到主窗口槽函数 RecvAndSetForegroundColor() ,当用户在非模态的前景色对话框点选颜色时,主界面的标签前景色自动同步更新。
析构函数里删除了前景色对话框,并将指针置空。

下面我们编辑“设置前景色”按钮槽函数和动态更新前景色槽函数的内容:
//设置前景色按钮
void WidgetCustomizeLabel::on_pushButtonForeground_clicked()
{
    m_pDlgForeground->show();
    m_pDlgForeground->raise();
}

//槽函数,动态更新前景色
void WidgetCustomizeLabel::RecvAndSetForegroundColor(QColor color)
{
    if( ! color.isValid())
    {
        return;  //颜色不合法
    }
    //颜色值合法
    m_clrForeground = color;
    QString strQSS = tr("color: %1; background-color: %2;")
            .arg(m_clrForeground.name()).arg(m_clrBackground.name());
    ui->labelSample->setStyleSheet( strQSS );
}
“设置前景色”按钮槽函数里面,将前景色对话框按照非模态显示,并显示到前端,方便用户操作。
当用户在前景色对话框修改颜色时,发出 currentColorChanged() 信号,调用 RecvAndSetForegroundColor() 槽函数,这个槽函数先判断参数的颜色是否合法,如果颜色值不合法就返回。
对于合法颜色,保存颜色到成员变量 m_clrForeground;
根据新的前景色和已有背景色,构造样式表字符串,设置给 ui->labelSample,这样就完成前景色同步更新。
前景色是通过自定义颜色对话框获取,并采用非模态对话框持续显示的方式实现。

实际中通用对话框的静态函数使用方式更为方便快捷,我们下面三个按钮槽函数都是使用静态函数,显示模态对话框获取数据。
我们编辑“设置背景色”按钮内容如下:
//设置背景色按钮
void WidgetCustomizeLabel::on_pushButtonBackground_clicked()
{
    //获取颜色
    QColor clr = QColorDialog::getColor();
    if( ! clr.isValid())
    {
        return;
    }
    //合法颜色
    m_clrBackground = clr;
    QString strQSS = tr("color: %1; background-color: %2;")
            .arg(m_clrForeground.name()).arg(m_clrBackground.name());
    ui->labelSample->setStyleSheet( strQSS );
}
对于背景色,我们直接调用 QColorDialog::getColor() 获取颜色存到 clr ;
判断 clr 颜色是否合法,如果不合法直接返回,这种情况是用户点击“Cancel”按钮或按了 Esc 键,取消了颜色选取操作。
如果颜色合法,将颜色存到成员变量 m_clrBackground;
根据前景色和背景色成员变量,构造样式表字符串,设置给标签 ui->labelSample,完成背景色的一次性设置。
使用静态函数,就不需要单独编写对话框对象构造、信号槽函数关联等代码,一步到位就拿到了输入值,比较方便快捷。

“设置字体”按钮槽函数代码如下:
//设置字体按钮
void WidgetCustomizeLabel::on_pushButtonFont_clicked()
{
    //获取字体
    bool bOK = false;
    QFont ft = QFontDialog::getFont( &bOK, m_font );
    if( ! bOK )
    {
        return; //取消了
    }
    m_font = ft;
    //设置新字体
    ui->labelSample->setFont( m_font );
}
该函数里我们定义了 bOK 变量,用于保存对话框的“OK”或“Cancel”按钮点击状态;
使用 QFontDialog::getFont( &bOK, m_font ) 获取字体,字体对话框的默认初始字体就是上次设置的 m_font;
判断对话框结束状态 bOK ,如果是点击“Cancel”按钮,bOK 是 false 就直接返回;
如果点击了“OK”按钮,bOK  是 true,那么正确获取了新字体,保存字体到成员变量 m_font;
将 m_font 设置给 ui->labelSample,这样就完成了字体修改。

“设置文本”按钮槽函数代码如下:
//设置文本按钮
void WidgetCustomizeLabel::on_pushButtonText_clicked()
{
    //获取输入文本
    bool bOK = false;
    QString strText = QInputDialog::getMultiLineText(this, tr("设置文本"),tr("请输入文本:"),
                                                     m_strText, &bOK);
    if( ! bOK )
    {
        return; //取消了
    }
    m_strText = strText;
    ui->labelSample->setText(m_strText);
}
该函数里我们定义了 bOK 变量,用于保存对话框的“OK”或“Cancel”按钮点击状态;
使用 QInputDialog::getMultiLineText() 获取多行文本,对话框默认文本就是上次设置的旧文本内容m_strText;
判断对话框结束状态 bOK ,如果是点击“Cancel”按钮,bOK 是 false 就直接返回;
如果点击了“OK”按钮,bOK  是 true,那么正确获取了新文本,将新文本存到 m_strText,
并将新文本 m_strText 设置给 ui->labelSample,这样就完成了文本修改。

代码编辑完成,我们构建项目并运行示例, 测试各个按钮功能:
run1
前景色对话框是非模态的,可以持续显示,与主窗口可以自由切换输入焦点,用户点击颜色,主窗口标签前景色同步更新。
其他三个按钮对应的对话框是模态显示,必须点击“OK”按钮关闭模态对话框,获取的数据才会传递给主窗口,进行更新操作。读者可以自行测试例子的功能。

通过示例代码,我们可以发现使用 Qt 通用对话框的优点:
① 使用 Qt 通用对话框非常方便快捷,不需要额外创建对话框类文件、界面文件,减少项目内的文件数量;
② 使用通用对话框的静态函数获取数据,就不需要定义对话框对象,也不用关联信号和槽函数,节约编写代码工作量。
本节内容介绍到这,下一节我们继续学习 Qt 通用对话框。



prev
contents
next