目录
源文件 (ClickableCircleWidget.cpp)
2.添加一个点击事件,且只有绿色状态可以响应事件,灰色状态不能点击
源文件 (ClickableCircleWidget.cpp)
源文件 (ClickableCircleWidget.cpp)
1.需求:qt 创建一个可以点击的图片,图片为圆形,背景透明,根据状态可以设置灰和绿两种颜色
1.概要
创建一个原型的控件,最关键的就是重绘,重新控件的重绘事件paintEvent,使用QPainter对象进行重绘。
2.内容
在 Qt 中创建一个可点击的圆形图片控件,可以使用自定义的 QWidget。你可以通过重写 paintEvent
来绘制圆形和文字,并通过鼠标事件来实现点击功能。下面是一个简单的例子:
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QMouseEvent>
class ClickableCircleWidget : public QWidget
{
Q_OBJECT
public:
explicit ClickableCircleWidget(QWidget *parent = nullptr)
: QWidget(parent), isGreen(false)
{
setAttribute(Qt::WA_TranslucentBackground);
}
void setGreen(bool green)
{
isGreen = green;
update();
}
protected:
void paintEvent(QPaintEvent *event) override
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// Determine the size of the circle
int side = qMin(width(), height());
int radius = side / 2;
// Set the brush color based on the current state
QColor color = isGreen ? Qt::green : Qt::gray;
painter.setBrush(color);
painter.setPen(Qt::NoPen);
// Draw the circle
painter.drawEllipse(0, 0, side, side);
// Set the text properties
painter.setPen(Qt::white);
QFont font = painter.font();
font.setPointSize(radius / 3); // Adjust the font size based on the circle size
font.setBold(true);
painter.setFont(font);
// Draw the text in the center of the circle
painter.drawText(rect(), Qt::AlignCenter, "监");
}
void mousePressEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
// Toggle the color state on click
isGreen = !isGreen;
emit clicked();
update();
}
}
signals:
void clicked();
private:
bool isGreen;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ClickableCircleWidget widget;
widget.resize(200, 200); // Set the desired size
widget.show();
QObject::connect(&widget, &ClickableCircleWidget::clicked, []() {
qDebug("Circle was clicked!");
});
return a.exec();
}
#include "main.moc"
解释:
- QWidget 子类化:
ClickableCircleWidget
继承自QWidget
,用于创建自定义控件。
- 透明背景:
setAttribute(Qt::WA_TranslucentBackground);
用于设置控件背景透明。
- 绘制事件 (
paintEvent
):- 在
paintEvent
中,使用QPainter
绘制一个圆形,并根据isGreen
状态设置颜色。 - 圆形的直径取控件的宽和高中的最小值,以保证圆形。
- 在
- 鼠标按下事件 (
mousePressEvent
):- 在
mousePressEvent
中,检测鼠标左键点击事件,并切换isGreen
状态,然后调用update()
重新绘制控件。
- 在
- 信号槽机制:
- 定义
clicked
信号,用于在控件被点击时发出信号。
- 定义
main
函数:- 在
main
函数中创建ClickableCircleWidget
实例并显示。 - 连接
clicked
信号到一个简单的调试输出槽函数。
- 在
你可以根据需要调整控件的大小、字体大小、颜色等属性。
3.关联链接
4.关联知识
1.painter::drawEllipse
QPainter::drawEllipse
是 Qt 框架中用于绘制椭圆的方法。它是 QPainter
类的一部分,QPainter
类提供了丰富的绘图功能,用于在 QWidgets 和其他绘图设备(如 QPixmap、QImage)上进行绘图。
使用 drawEllipse
drawEllipse
方法用于在当前的 QPainter
绘制上下文中绘制一个椭圆。你可以通过指定椭圆的左上角坐标和宽高来定义椭圆的大小和位置。
方法签名
void QPainter::drawEllipse(const QRectF &rectangle);
void QPainter::drawEllipse(int x, int y, int width, int height);
void QPainter::drawEllipse(const QPoint &topLeft, int width, int height);
参数说明
const QRectF &rectangle
:- 使用
QRectF
对象指定椭圆的边界矩形。
- 使用
int x, int y, int width, int height
:x
和y
指定椭圆左上角的位置。width
和height
指定椭圆的宽度和高度。
const QPoint &topLeft, int width, int height
:topLeft
是一个QPoint
对象,指定椭圆左上角的位置。width
和height
指定椭圆的宽度和高度。
示例
以下是如何在 paintEvent
中使用 drawEllipse
绘制一个椭圆的简单示例:
#include <QApplication>
#include <QWidget>
#include <QPainter>
class EllipseWidget : public QWidget
{
protected:
void paintEvent(QPaintEvent *event) override
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing); // Enable antialiasing for smoother edges
// Draw an ellipse with a specific bounding rectangle
painter.drawEllipse(50, 50, 100, 150);
// Alternatively, you can use QRectF
QRectF rect(200, 50, 100, 150);
painter.drawEllipse(rect);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
EllipseWidget window;
window.resize(400, 300);
window.show();
return app.exec();
}
说明
- 抗锯齿:通过调用
painter.setRenderHint(QPainter::Antialiasing)
可以启用抗锯齿,从而使椭圆的边缘更加平滑。 - 坐标系统:在 Qt 的坐标系统中,原点 (0,0) 位于窗口的左上角,x 轴向右延伸,y 轴向下延伸。
通过使用 drawEllipse
方法,你可以轻松地在 Qt 应用程序中绘制各种形状和大小的椭圆。
2.QFont::setPointSize
QFont::setPointSize
是 Qt 框架中 QFont
类的一个成员函数,用于设置字体的点大小(point size)。点大小是一种常用的字体尺寸单位,通常用于桌面应用程序的字体设置。
一、函数原型
void QFont::setPointSize(int pointSize);
二、参数
pointSize
:一个整数,表示字体的点大小。通常,点大小的范围在 0 到一个较大的整数值之间,但具体的最大值可能取决于平台和字体渲染引擎的实现。在大多数情况下,常用的点大小范围在 6 到 72 之间。
三、功能
QFont::setPointSize
函数用于将字体的点大小设置为指定的值。点大小是相对于设备分辨率的,因此它在不同的设备上可能会有所不同。但是,Qt 会尽量保持字体大小的一致性,以确保跨平台的良好显示效果。- 设置点大小后,字体的大小将发生变化,这会影响使用该字体的所有文本绘制操作。
四、使用示例
以下是一个简单的示例,演示如何使用 QFont::setPointSize
设置字体的点大小:
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QFont>
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event) override {
QPainter painter(this);
QFont font;
font.setPointSize(16); // 设置字体点大小为16
painter.setFont(font);
painter.drawText(50, 50, "Hello, Qt with point size 16!");
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyWidget window;
window.resize(300, 100);
window.show();
return app.exec();
}
在上面的示例中,我们创建了一个自定义的 QWidget
子类 MyWidget
,并在其 paintEvent()
函数中使用 QPainter
绘制文本。在绘制文本之前,我们创建了一个 QFont
对象,并使用 setPointSize(16)
将其点大小设置为 16。然后,我们将这个字体应用到 QPainter
对象上,并绘制了一段文本。
五、注意事项
- 点大小与像素大小的区别:点大小是一种相对大小,而像素大小是绝对的。在不同的设备和分辨率下,同一个点大小可能会显示为不同的像素大小。Qt 会根据设备的分辨率和字体渲染引擎的实现来自动调整字体大小。
- 跨平台一致性:虽然点大小在不同平台上可能会有所不同,但 Qt 会尽量保持字体大小的一致性。然而,由于不同平台的字体渲染方式和默认字体可能不同,因此在实际应用中仍然可能需要进行一些微调。
- 性能考虑:频繁地更改字体大小可能会影响性能,尤其是在需要大量文本绘制的场景中。因此,在可能的情况下,应该尽量减少字体大小的更改次数。
六、总结
QFont::setPointSize
是设置字体点大小的一个简单而有效的方法。通过合理使用点大小,可以轻松地控制文本的大小和显示效果。无论是在桌面应用程序还是其他类型的应用程序中,QFont::setPointSize
都是一个非常常用的函数。
2.QPainter
QPainter 是 Qt 框架中的一个核心绘图类,用于在各种设备上进行高效的 2D 图形绘制。它提供了一系列丰富的函数,支持绘制点、线、曲线、形状、文本、图像以及复杂的绘画操作。以下是关于 QPainter 的详细介绍:
一、基本概念
- QPainter 是 Qt 绘图系统的核心,它通过与绘图设备(如窗口部件、图像、像素图等)关联,执行具体的绘图操作。
- QPaintDevice 是一个抽象的二维空间,是所有可被 QPainter 绘制的设备的基类。它本身不直接绘制物理显示画面,而是作为逻辑界面的中间媒介。例如,QWidget、QPixmap、QImage 等都是 QPaintDevice 的子类。
- QPaintEngine 提供了 QPainter 在不同的设备上进行绘制的接口。它位于 QPainter 和 QPaintDevice 之间,负责将绘图操作转换为设备能理解的命令。通常,开发人员不需要直接操作 QPaintEngine。
二、主要功能
-
基本图形绘制
- 点、线、曲线:使用
drawPoint()
、drawLine()
、drawPolyline()
、drawCubicBezier()
等函数,可以绘制点、直线、折线、贝塞尔曲线等。 - 形状:通过
drawRect()
、drawEllipse()
、drawPie()
、drawRoundedRect()
、drawPolygon()
等函数,可以绘制矩形、椭圆、扇形、圆角矩形、多边形等。 - 文本:使用
drawText()
函数,可以在指定位置绘制文本。通过设置 QFont 对象,可以控制文本的字体、大小、样式等。 - 图像:使用
drawImage()
、drawPixmap()
函数,可以将 QImage 或 QPixmap 对象绘制到绘图设备上。
- 点、线、曲线:使用
-
高级特性
- 反走样:通过设置
setRenderHint(QPainter::Antialiasing, true)
,可以开启抗锯齿功能,使绘制的图形边缘更加平滑。 - 渐变填充:使用 QLinearGradient 或 QRadialGradient 创建渐变对象,再将其设置为 QBrush 的样式,可以实现渐变填充效果。
- 坐标变换:支持平移、旋转、缩放、剪切等几何变换,通过调用
translate()
、rotate()
、scale()
、shear()
等函数,可以影响后续的绘图操作。 - 裁剪:使用
setClipRect()
函数,可以限制绘图的区域,只有在这个区域内的内容才会被绘制。
- 反走样:通过设置
-
画笔和画刷
- QPen:用于定义线条的颜色、宽度、样式、线端点和连接样式等。通过
setPen()
函数,可以将 QPen 对象应用到 QPainter 上。 - QBrush:用于定义填充区域的样式,如纯色、渐变、纹理等。通过
setBrush()
函数,可以将 QBrush 对象应用到 QPainter 上。
- QPen:用于定义线条的颜色、宽度、样式、线端点和连接样式等。通过
三、使用方法
-
创建 QPainter 对象
-
可以直接创建一个 QPainter 对象,并通过
begin()
函数将其与 QPaintDevice 关联。例如:QPixmap pixmap(400, 300); QPainter painter(&pixmap); if (!painter.isActive()) { painter.begin(&pixmap); }
-
也可以在创建 QPainter 对象时,直接传入 QPaintDevice 指针进行关联。例如:
QPixmap pixmap(400, 300); QPainter painter(&pixmap);
-
在 Qt5 之后,通常可以直接在构造函数中初始化并开始绘图,但在某些情况下(如设备不可用),仍需要检查
painter.isActive()
的返回值。
-
-
设置绘图属性
- 使用
setPen()
、setBrush()
、setFont()
等函数,设置绘图属性,如线条颜色、填充样式、字体等。
- 使用
-
执行绘图操作
- 调用 QPainter 提供的绘图函数,如
drawLine()
、drawRect()
、drawText()
等,执行具体的绘图操作。
- 调用 QPainter 提供的绘图函数,如
-
结束绘图并释放资源
- 使用
end()
函数结束绘图,并释放相关资源。这是一个良好的编程习惯,可以防止资源泄漏。
- 使用
四、应用场景
- 自定义控件:当 Qt 提供的标准控件无法满足需求时,可以使用 QPainter 自定义控件的绘制逻辑。
- 图形界面绘制:在窗口部件的重绘事件(
paintEvent()
)中,使用 QPainter 绘制复杂的图形界面。 - 图像处理和生成:使用 QPainter 在 QImage 或 QPixmap 对象上进行绘图操作,实现图像处理和生成功能。
- 打印和 PDF 生成:与 QPrinter 对象结合使用,可以将图形输出到打印机,或生成 PDF 文档。
五、示例代码
以下是一个简单的示例,演示如何在 QWidget 上绘制矩形和文本:
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QFont>
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event) override {
QPainter painter(this);
// 设置画笔颜色为红色
QPen pen(Qt::red);
painter.setPen(pen);
// 设置画刷颜色为蓝色
QBrush brush(Qt::blue);
painter.setBrush(brush);
// 绘制一个矩形
painter.drawRect(50, 50, 200, 100);
// 设置字体
QFont font;
font.setPointSize(16);
font.setBold(true);
painter.setFont(font);
// 绘制文本
painter.drawText(100, 100, "Hello, Qt!");
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyWidget window;
window.resize(300, 200);
window.show();
return app.exec();
}
在上面的示例中,我们创建了一个自定义的 QWidget 子类 MyWidget
,并在其 paintEvent()
函数中使用 QPainter 绘制了一个矩形和一段文本。通过设置画笔(QPen)和画刷(QBrush)的颜色,以及字体的样式,可以控制绘制效果。
六、总结
QPainter 是 Qt 框架中功能强大的绘图类,它提供了丰富的 API,支持绘制各种基本图形和高级特性。通过合理使用 QPainter,可以实现复杂的图形界面和图像处理功能。无论是在桌面应用程序开发,还是在嵌入式系统、游戏开发等领域,QPainter 都发挥着重要的作用。
3.QPainter常用接口
QPainter 是 Qt 框架中用于执行绘图操作的类,提供了丰富的接口来满足各种 2D 图形绘制的需求。以下是 QPainter 常用接口的介绍:
1. 基本绘图操作
-
绘制点、线、曲线
drawPoint(const QPointF &point)
: 绘制一个点。drawPoints(const QPointF *points, int pointCount)
: 绘制多个点。drawLine(const QPointF &p1, const QPointF &p2)
: 绘制一条直线。drawLines(const QLineF *lines, int lineCount)
: 绘制多条直线。drawPolyline(const QPointF *points, int pointCount)
: 绘制一个折线(由直线段组成)。drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule = Qt::OddEvenFill)
: 绘制一个多边形。drawEllipse(const QRectF &rect)
: 绘制一个椭圆(如果矩形是正方形,则绘制一个圆)。drawArc(const QRectF &rect, int startAngle, int spanAngle)
: 绘制一个圆弧。drawChord(const QRectF &rect, int startAngle, int spanAngle)
: 绘制一个弦(圆弧与矩形相交的两点之间的线段)。drawPie(const QRectF &rect, int startAngle, int spanAngle)
: 绘制一个扇形(圆弧与两条半径围成的区域)。drawRect(const QRectF &rect)
: 绘制一个矩形。drawRects(const QRectF *rects, int rectCount)
: 绘制多个矩形。drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode = Qt::AbsoluteSize)
: 绘制一个圆角矩形。drawPath(const QPainterPath &path)
: 绘制一个复杂的路径(由直线段、曲线段组成)。
-
绘制文本
drawText(const QPointF &position, const QString &text)
: 在指定位置绘制文本。drawText(const QRectF &rectangle, int flags, const QString &text)
: 在指定矩形区域内按照指定标志绘制文本。drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect = nullptr)
: 类似上一个方法,但使用 QRect 而不是 QRectF。boundingRect(const QRectF &rectangle, int flags, const QString &text)
: 返回在给定矩形内绘制文本所需的边界矩形。
-
绘制图像和像素图
drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect = QRectF(), Qt::ImageConversionFlags flags = Qt::AutoColor)
: 在目标矩形区域内绘制图像的一部分。drawImage(const QPoint &point, const QImage &image, const QRectF &sourceRect = QRectF(), Qt::ImageConversionFlags flags = Qt::AutoColor)
: 在指定位置绘制图像的一部分。drawImage(const QRectF &r, const QImage &image)
: 绘制整个图像到目标矩形区域内。drawPixmap(const QPointF &point, const QPixmap &pixmap)
: 在指定位置绘制一个像素图。drawPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QRectF &sourceRectangle = QRectF())
: 在目标矩形区域内绘制像素图的一部分。
2. 设置绘图属性
-
画笔(QPen)
setPen(const QPen &pen)
: 设置画笔属性,如颜色、宽度、线型等。
-
画刷(QBrush)
setBrush(const QBrush &brush)
: 设置画刷属性,如颜色、填充样式、渐变等。
-
字体(QFont)
setFont(const QFont &font)
: 设置字体属性,如字体样式、大小等。
-
渲染提示
setRenderHint(QPainter::RenderHint hint, bool on = true)
: 启用或禁用指定的渲染提示,如抗锯齿(QPainter::Antialiasing
)、文本抗锯齿(QPainter::TextAntialiasing
)等。
3. 坐标变换
-
平移
translate(qreal dx, qreal dy)
: 平移坐标系统。
-
旋转
rotate(qreal angle)
: 旋转坐标系统。
-
缩放
scale(qreal sx, qreal sy)
: 缩放坐标系统。
-
剪切
shear(qreal sh, qreal sv)
: 剪切坐标系统。
4. 状态管理
-
保存和恢复状态
save()
: 保存当前绘图状态。restore()
: 恢复之前保存的绘图状态。
-
剪辑区域
setClipRect(const QRectF &rectangle, Qt::ClipOperation operation = Qt::ReplaceClip)
: 设置剪辑区域。setClipPath(const QPainterPath &path, Qt::ClipOperation operation = Qt::ReplaceClip)
: 设置剪辑路径。
-
透明度
setOpacity(qreal opacity)
: 设置全局透明度。
-
图形合成模式
setCompositionMode(QPainter::CompositionMode mode)
: 设置图形合成模式,影响图形与图形的叠加方式。
5. 其他常用接口
-
构造函数和初始化
QPainter()
: 创建一个未绑定到绘图设备的 QPainter 对象。在使用此对象进行绘图之前,必须通过begin(QPaintDevice *device)
方法将其绑定到一个绘图设备,如 QWidget、QPixmap、QImage 等。
-
销毁对象
- 在绘图完成后,应销毁 QPainter 对象或让其在局部作用域内自动销毁,以避免资源泄露。
注意事项
-
绘图事件
- 通常在控件的
paintEvent()
方法中使用 QPainter 进行绘图,以确保绘图操作与 Qt 的绘制机制同步。
- 通常在控件的
-
属性设置
- 绘图前,应设置好 QPainter 的各项属性(如画笔、画刷、字体等),以提高绘图效率和质量。
QPainter 提供的这些接口使得开发者能够方便地在各种绘图设备上绘制出丰富多样的图形和文本,满足各种应用场景的需求。
4.Q_UNUSED(event)
Q_UNUSED(event);
是 Qt 框架中常用的一个宏,主要用于在代码中显式地表明某个参数未被使用,以避免编译器发出未使用变量的警告。
使用场景
通常在事件处理函数或者一些重载函数中,我们可能不需要使用传入的参数。例如:
void MyWidget::mouseMoveEvent(QMouseEvent *event)
{
Q_UNUSED(event);
// 此处并未实际使用 event 参数,但为了避免编译器警告,使用 Q_UNUSED 宏标记
qDebug() << "Mouse is moving!";
}
作用
- 避免编译器警告:如果函数参数未使用,编译器通常会生成未使用变量的警告,这在保持代码整洁时可能会造成干扰。
- 提高代码可读性:通过显式地声明未使用的变量,其他开发者能够更清楚地理解这是有意忽略的参数。
原理
Q_UNUSED
宏的定义非常简单,在 Qt 的头文件中通常是这样实现的:
#define Q_UNUSED(x) (void)(x)
通过将变量强制转换为 void
,它告诉编译器这是一个有意忽略的操作,从而消除警告。
总结
Q_UNUSED(event);
是一种简单有效的方法,用来在 Qt 项目中忽略未使用的变量,同时保持代码的清晰和整洁。
5.项目升级
1.头文件和资源文件分开
当然,可以将 ClickableCircleWidget
的代码拆分为头文件和源文件,以便于更好地组织和管理代码。以下是拆分后的代码结构:
头文件 (ClickableCircleWidget.h
)
#ifndef CLICKABLECIRCLEWIDGET_H
#define CLICKABLECIRCLEWIDGET_H
#include <QWidget>
class ClickableCircleWidget : public QWidget
{
Q_OBJECT
public:
explicit ClickableCircleWidget(QWidget *parent = nullptr);
void setGreen(bool green);
signals:
void clicked();
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
private:
bool isGreen;
};
#endif // CLICKABLECIRCLEWIDGET_H
源文件 (ClickableCircleWidget.cpp
)
#include "ClickableCircleWidget.h"
#include <QPainter>
#include <QMouseEvent>
#include <QDebug>
ClickableCircleWidget::ClickableCircleWidget(QWidget *parent)
: QWidget(parent), isGreen(false)
{
setAttribute(Qt::WA_TranslucentBackground);
}
void ClickableCircleWidget::setGreen(bool green)
{
isGreen = green;
update();
}
void ClickableCircleWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// Determine the size of the circle
int side = qMin(width(), height());
int radius = side / 2;
// Set the brush color based on the current state
QColor color = isGreen ? Qt::green : Qt::gray;
//设置画笔和画刷
painter.setBrush(color);
painter.setPen(Qt::NoPen);
// Draw the circle
//画一个椭圆,宽高相同
painter.drawEllipse(0, 0, side, side);
// Set the text properties
// 写入文本
painter.setPen(Qt::white);
QFont font = painter.font();
//设置文本的大小为控件的1/6 int radius = side / 2;和radius / 3
font.setPointSize(radius / 3); // Adjust the font size based on the circle size
font.setBold(true);
painter.setFont(font);
// Draw the text in the center of the circle
// 居中绘制文本
painter.drawText(rect(), Qt::AlignCenter, "监");
}
void ClickableCircleWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
//这里就是只有按钮是绿色的时候才会响应点击事件的关键
// Toggle the color state on click
isGreen = !isGreen;
emit clicked();
update();
}
}
main.cpp
#include <QApplication>
#include "ClickableCircleWidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ClickableCircleWidget widget;
widget.resize(200, 200); // Set the desired size
widget.show();
QObject::connect(&widget, &ClickableCircleWidget::clicked, []() {
qDebug("Circle was clicked!");
});
return a.exec();
}
项目文件 (CMakeLists.txt
或 .pro
)
根据你使用的构建系统,以下是简单的项目文件示例。
使用 qmake 的 .pro
文件
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ClickableCircleApp
TEMPLATE = app
SOURCES += main.cpp \
ClickableCircleWidget.cpp
HEADERS += ClickableCircleWidget.h
使用 CMake 的 CMakeLists.txt
文件
cmake_minimum_required(VERSION 3.5)
project(ClickableCircleApp VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
add_executable(ClickableCircleApp
main.cpp
ClickableCircleWidget.cpp
ClickableCircleWidget.h
)
target_link_libraries(ClickableCircleApp PRIVATE Qt5::Widgets)
说明
- 头文件:声明了
ClickableCircleWidget
类,包括其构造函数、方法、信号以及受保护的事件处理函数。 - 源文件:实现了类的构造函数、绘制逻辑、鼠标事件处理函数以及信号的发射。
main.cpp
:创建应用程序实例,初始化并显示ClickableCircleWidget
。- 项目文件:根据使用的构建系统选择合适的文件进行项目管理。
2.添加一个点击事件,且只有绿色状态可以响应事件,灰色状态不能点击
要点:
void ClickableCircleWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && isGreen) {
// Only respond to clicks when the circle is green
// 这里控制只有绿色安状态会发送点击的消息
emit clicked();
update(); // Optional: you might want to update the UI if needed
}
}
为了实现你所描述的功能,我们需要在 ClickableCircleWidget
类中添加一个机制,使得只有在绿色状态下才能响应点击事件。在灰色状态下,点击事件将不被处理。
下面是更新后的代码:
头文件 (ClickableCircleWidget.h
)
#ifndef CLICKABLECIRCLEWIDGET_H
#define CLICKABLECIRCLEWIDGET_H
#include <QWidget>
class ClickableCircleWidget : public QWidget
{
Q_OBJECT
public:
explicit ClickableCircleWidget(QWidget *parent = nullptr);
void setGreen(bool green);
signals:
void clicked();
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
private:
bool isGreen;
};
#endif // CLICKABLECIRCLEWIDGET_H
源文件 (ClickableCircleWidget.cpp
)
#include "ClickableCircleWidget.h"
#include <QPainter>
#include <QMouseEvent>
#include <QDebug>
ClickableCircleWidget::ClickableCircleWidget(QWidget *parent)
: QWidget(parent), isGreen(false)
{
setAttribute(Qt::WA_TranslucentBackground);
}
void ClickableCircleWidget::setGreen(bool green)
{
isGreen = green;
update();
}
void ClickableCircleWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// Determine the size of the circle
int side = qMin(width(), height());
int radius = side / 2;
// Set the brush color based on the current state
QColor color = isGreen ? Qt::green : Qt::gray;
painter.setBrush(color);
painter.setPen(Qt::NoPen);
// Draw the circle
painter.drawEllipse(0, 0, side, side);
// Set the text properties
painter.setPen(Qt::white);
QFont font = painter.font();
font.setPointSize(radius / 3); // Adjust the font size based on the circle size
font.setBold(true);
painter.setFont(font);
// Draw the text in the center of the circle
painter.drawText(rect(), Qt::AlignCenter, "监");
}
void ClickableCircleWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && isGreen) {
// Only respond to clicks when the circle is green
// 这里控制只有绿色安状态会发送点击的消息
emit clicked();
update(); // Optional: you might want to update the UI if needed
}
}
main.cpp
#include <QApplication>
#include "ClickableCircleWidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ClickableCircleWidget widget;
widget.resize(200, 200); // Set the desired size
widget.show();
QObject::connect(&widget, &ClickableCircleWidget::clicked, []() {
qDebug() << "Circle was clicked!";
});
return a.exec();
}
说明
mousePressEvent
:在mousePressEvent
方法中,添加了一个条件检查isGreen
。只有当isGreen
为true
时,才会处理点击事件并发射clicked
信号。setGreen
方法:用于设置圆圈的状态(绿色或灰色),并在状态改变时调用update()
方法重新绘制组件。
通过这种方式,你可以在绿色状态下响应点击事件,而在灰色状态下忽略点击事件。
3.让文本可以设置
要点:
private:
bool isGreen;
QString text;
void setText(const QString &text);
void ClickableCircleWidget::setText(const QString &newText)
{
text = newText;
update(); // Redraw the widget with the new text
}
// Draw the text in the center of the circle
painter.drawText(rect(), Qt::AlignCenter, text);
为了实现让文本可以动态设置的功能,我们可以在 ClickableCircleWidget
类中添加一个设置文本的方法。这样,你可以在应用程序中随时更改圆圈内的文本。
下面是更新后的代码:
头文件 (ClickableCircleWidget.h
)
#ifndef CLICKABLECIRCLEWIDGET_H
#define CLICKABLECIRCLEWIDGET_H
#include <QWidget>
#include <QString>
class ClickableCircleWidget : public QWidget
{
Q_OBJECT
public:
explicit ClickableCircleWidget(QWidget *parent = nullptr);
void setGreen(bool green);
void setText(const QString &text);
signals:
void clicked();
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
private:
bool isGreen;
QString text;
};
#endif // CLICKABLECIRCLEWIDGET_H
源文件 (ClickableCircleWidget.cpp
)
#include "ClickableCircleWidget.h"
#include <QPainter>
#include <QMouseEvent>
#include <QDebug>
ClickableCircleWidget::ClickableCircleWidget(QWidget *parent)
: QWidget(parent), isGreen(false), text("监") // Default text
{
setAttribute(Qt::WA_TranslucentBackground);
}
void ClickableCircleWidget::setGreen(bool green)
{
isGreen = green;
update();
}
void ClickableCircleWidget::setText(const QString &newText)
{
text = newText;
update(); // Redraw the widget with the new text
}
void ClickableCircleWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// Determine the size of the circle
int side = qMin(width(), height());
int radius = side / 2;
// Set the brush color based on the current state
QColor color = isGreen ? Qt::green : Qt::gray;
painter.setBrush(color);
painter.setPen(Qt::NoPen);
// Draw the circle
painter.drawEllipse(0, 0, side, side);
// Set the text properties
painter.setPen(Qt::white);
QFont font = painter.font();
font.setPointSize(radius / 3); // Adjust the font size based on the circle size
font.setBold(true);
painter.setFont(font);
// Draw the text in the center of the circle
painter.drawText(rect(), Qt::AlignCenter, text);
}
void ClickableCircleWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && isGreen) {
// Only respond to clicks when the circle is green
emit clicked();
update(); // Optional: you might want to update the UI if needed
}
}
main.cpp
#include <QApplication>
#include "ClickableCircleWidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ClickableCircleWidget widget;
widget.resize(200, 200); // Set the desired size
widget.setText("Hello"); // Set the text to "Hello"
widget.show();
QObject::connect(&widget, &ClickableCircleWidget::clicked, []() {
qDebug() << "Circle was clicked!";
});
return a.exec();
}
说明
setText
方法:添加了一个新的setText
方法,用于设置圆圈内的文本。每次调用setText
时,都会调用update()
方法来重新绘制组件以显示新的文本。- 构造函数:在构造函数中,将默认文本设置为
"监"
,但你可以通过setText
方法随时更改它。
这样,你就可以在应用程序中动态设置圆圈的文本内容了。
6.其他参考方案
1.需求:qt 创建一个可以点击的图片,图片为圆形,背景透明,根据状态可以设置灰和绿两种颜色
在 Qt 中创建一个可以点击的圆形图片,并根据状态更改颜色,可以使用 QPushButton
和自定义的样式表来实现。以下是一个简单的示例代码,展示如何实现这一功能:
#include <QApplication>
#include <QPushButton>
#include <QStyleOptionButton>
#include <QPainter>
class RoundButton : public QPushButton {
Q_OBJECT
public:
explicit RoundButton(QWidget *parent = nullptr) : QPushButton(parent) {
setFixedSize(100, 100); // 设置按钮大小
setCheckable(true); // 使按钮可以被选中
setStyleSheet("QPushButton { border: none; }"); // 去掉默认边框
}
protected:
void paintEvent(QPaintEvent *event) override {
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing); // 抗锯齿
QColor fillColor = isChecked() ? Qt::green : Qt::gray; // 根据状态设置颜色
painter.setBrush(fillColor);
painter.setPen(Qt::NoPen); // 无边框
// 画一个圆形
painter.drawEllipse(rect());
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建窗口
QWidget window;
window.setFixedSize(200, 200);
// 创建圆形按钮
RoundButton *button = new RoundButton(&window);
button->setGeometry(50, 50, 100, 100); // 设置按钮的位置和大小
QObject::connect(button, &QPushButton::clicked, []() {
qDebug("Button clicked!");
});
window.show();
return app.exec();
}
#include "main.moc"
说明
- RoundButton 类:
- 继承自
QPushButton
,并重写了paintEvent
方法来自定义绘制按钮的外观。 - 使用
QPainter
绘制一个圆形,根据按钮的选中状态(isChecked()
)设置不同的填充颜色。
- 继承自
- 设置样式:
- 使用
setStyleSheet
去掉了按钮的默认边框。
- 使用
- 主函数:
- 创建一个简单的窗口,并在窗口中添加一个
RoundButton
实例。 - 连接按钮的
clicked
信号到一个简单的调试输出槽函数。
- 创建一个简单的窗口,并在窗口中添加一个
这样,你就得到了一个可以点击的圆形按钮,当按钮被选中时,它会改变颜色。你可以根据需要调整按钮的大小和颜色。