Qt学习例子15——objectitem

本文介绍了一个使用Qt的程序实例,通过滑动条控制一个笑脸图形的大小,并实现鼠标悬停时眼睛跟随鼠标移动的效果。

此工程在上个例子之上加上了信号和槽,通过下面的滑动条控制笑脸的大小

 

依据此图而作:

Qt学习例子15鈥斺攐bjectitem

 

 
 

 

 

程序代码如下:

 

//main.cpp

 

#include <QtGui/QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QLayout>
#include <QSlider>
#include "smileyitem.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    QGraphicsView *view = new QGraphicsView;
    QGraphicsScene scene;
    view->setScene(&scene);
    SmileyItem *item = new SmileyItem;
    scene.addItem(item);
    item->setFlag(QGraphicsItem::ItemIsMovable);
    QSlider *slider = new QSlider(Qt::Horizontal);
    slider->setRange(0,100);
    slider->setValue(item->smileSize());
    QObject::connect(slider, SIGNAL(valueChanged(int)), item, SLOT(setSmileSize(int)));
    QObject::connect(item, SIGNAL(smileSizeChanged(int)), slider, SLOT(setValue(int)));
    QVBoxLayout *l = new QVBoxLayout(&w);
    l->addWidget(view);
    l->addWidget(slider);
    view->setRenderHint(QPainter::Antialiasing);
    w.show();
    w.resize(600,400);
    return a.exec();
}

 

 

//smileyitem.h

 

#ifndef SMILEYITEM_H
#define SMILEYITEM_H
#include <QGraphicsItem>
class SmileyItem : public QGraphicsObject
{
    Q_OBJECT
public:
    SmileyItem();
    QRectF boundingRect() const;
    QPainterPath shape() const;
    void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);
    int smileSize() const;
signals:
    void smileSizeChanged(int);
public slots:
    void setSmileSize(int);
protected:
    void paintEye(QPainter *painter, const QPointF &pt, const QPointF &focus, bool bigEye);
    void paintSmile(QPainter *painter, const QRectF &rect, int angle);
    void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
    void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
private:
    QPointF m_focus;
    bool m_bigEyes;
    int m_smileSize;
};
#endif // SMILEYITEM_H

 

 

//smileyitem.cpp

 

#include "smileyitem.h"
#include <QPainter>
#include <QGraphicsSceneHoverEvent>
#include <cmath>
QPoint computePupil (const QPoint &center, const QPoint &focus, int eyeWidth, int eyeHeight)
{
    QPointF dPoint = focus-center;
    if (dPoint.x() == 0 && dPoint.y() == 0) {
        return center;
    } else {
        double angle = atan2 (dPoint.y(), dPoint.x());
        double cosa = cos (angle);
        double sina = sin (angle);
        double h = hypot (eyeHeight * cosa, eyeWidth * sina);
        double x = (eyeWidth * eyeHeight) * cosa / h;
        double y = (eyeWidth * eyeHeight) * sina / h;
        double dist = hypot (x*0.7, y*0.7); //?
        if (dist > hypot (dPoint.x(), dPoint.y())) {
            return dPoint.toPoint()+center;
        } else {
            return QPoint(dist*cosa+center.x(), dist*sina+center.y());
        }
    }
}
SmileyItem::SmileyItem()
{
    setAcceptHoverEvents(true);
    m_bigEyes = false;
    m_smileSize = 100;
}
QRectF SmileyItem::boundingRect() const {
    return QRectF(-50, -50, 100, 100);
}
QPainterPath SmileyItem::shape() const {
    QPainterPath path;
    path.addEllipse(boundingRect());
    return path;
}
void SmileyItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget *widget ) {
    painter->setPen(Qt::NoPen);
    painter->setBrush(Qt::yellow);
    painter->drawEllipse(boundingRect());
    paintEye(painter, QPointF(-15,-25), m_focus, m_bigEyes);
    paintEye(painter, QPointF(15, -25), m_focus, m_bigEyes);
    paintSmile(painter, QRectF(-33, -12, 66, 50), 0.9*m_smileSize);
}
void SmileyItem::paintEye(QPainter *painter, const QPointF &pt, const QPointF &focus, bool bigEye){
    QPen pen(Qt::black);
    pen.setWidthF(1.5);
    painter->setPen(pen);
    painter->setBrush(Qt::white);
    QSize eyeSize(6,12);
    if(bigEye)
        eyeSize+=QSize(2,4);
    painter->drawEllipse(pt, eyeSize.width(), eyeSize.height());
    painter->setPen(Qt::NoPen);
    painter->setBrush(Qt::black);
    QPoint pupilPoint = focus.isNull() ? pt.toPoint() : computePupil(pt.toPoint(),focus.toPoint(),
                                                                     eyeSize.width(),eyeSize.height());
    painter->drawEllipse(pupilPoint, 2, 2);
}
void SmileyItem::paintSmile(QPainter *painter, const QRectF &rect, int angle) {
    QPen pen(Qt::black);
    pen.setWidthF(1.5);
    painter->setPen(pen);
    painter->drawArc(rect, -(90-angle)*16, -2*angle*16);
}
void SmileyItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) {
    m_focus = event->pos();
    update();
}
void SmileyItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
    m_focus = event->pos();
    update();
}
void SmileyItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) {
    m_focus = QPointF();
    update();
}
void SmileyItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
    m_bigEyes = true;
    update();
    QGraphicsItem::mousePressEvent(event);
}
void SmileyItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
    m_bigEyes = false;
    update();
    QGraphicsItem::mouseReleaseEvent(event);
}
int SmileyItem::smileSize() const {
    return m_smileSize;
}
void SmileyItem::setSmileSize(int size) {
    if(size==m_smileSize)
        return;
    m_smileSize=size;
    update();
    emit smileSizeChanged(size);
}

 

 

程序效果图如下:

Qt学习例子15鈥斺攐bjectitem

 

Qt学习例子15鈥斺攐bjectitem

### 使用 Qt 实现 K 线图 #### 创建自定义 QPushButton 类 为了在 Qt 应用程序中实现绘制 K 线图的功能,可以通过创建一个继承 `QPushButton` 的自定义类来完成。在这个类内部重写绘图事件处理方法,在用户点击按钮时触发相应的槽函数以更新图表数据并重新绘制。 ```cpp class CustomKLineButton : public QPushButton { Q_OBJECT public: explicit CustomKLineButton(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent *) override; }; ``` 此部分描述了如何构建用于显示 K 线图形件的基础结构[^1]。 #### 绘制 K 线图的具体实现 对于具体的绘制操作,则需利用 QPainter 对象来进行线条、矩形等几何形状的描绘工作。下面给出了一段 Python 代码片段作为例子说明怎样使用 PyQtGraph 来高效地渲染出美观且实用性强的金融资产价格走势曲线: ```python import pyqtgraph as pg from PyQt5 import QtWidgets class CandlestickItem(pg.GraphicsObject): def __init__(self, data): super().__init__() self.data = data self.generatePicture() def generatePicture(self): painter_path = QtGui.QPainterPath() for t, d in enumerate(self.data): open_, close, min_, max_ = d[:4] # Draw candle body and wick. rect = QtCore.QRectF(t - 0.3, open_, .6 ,close-open_) if close >= open_: painter_path.addRect(rect) p_minmax_line = QtCore.QPointF(t,min_) p_open_close_rect_top_left=QtCore.QPointF(t-.3,max_) painter_path.moveTo(p_minmax_line);painter_path.lineTo(p_open_close_rect_top_left) self.picture = QtGui.QPicture() painter = QtGui.QPainter(self.picture) painter.setRenderHint(QtGui.QPainter.Antialiasing,True) painter.drawPath(painter_path) painter.end() app = QtWidgets.QApplication([]) plt = pg.PlotWidget() item = CandlestickItem(data=[(89.72, 90.15, 89.37, 90.15), (90.15, 89.32, 88.88, 90.45)]) plt.addItem(item) plt.show() app.exec_() ``` 上述代码展示了基于 PyQT 和 PyQtGraph 结合的方式快速搭建起支持实时刷新特性的 K 线视图组件的方法[^2]。 #### UI 文件转换与集成 如果希望借助 Qt Designer 工具设计界面布局的话,则可先按照常规流程完成 `.ui` 文件的设计保存后再将其编译成对应的 Python 脚本以便后续开发过程中直接引用这些资源文件。具体来说就是在项目根目录下执行如下命令行指令即可达成目的: ```bash pyuic5 example1.ui -o ui_example1.py ``` 之后就可以像平常那样导入模块并在主窗口初始化阶段实例化所需的控件对象了[^3]。 #### C++ 版本实现细节补充 当然除了采用解释型语言外还可以考虑原生效率更高的 C++ 进行底层逻辑编码;这里提供一段简短却完整的源码用来展示整个过程的关键要点——即从零开始建立最小可行产品(MVP),进而围绕它逐步迭代完善直至最终形成稳定可靠的应用框架体系[^4]。 ```cpp #include <QApplication> #include <QWidget> #include <QVBoxLayout> #include <QCustomPlot> int main(int argc, char **argv){ QApplication app(argc, argv); QWidget window; QVBoxLayout* layout = new QVBoxLayout(&window); QCustomPlot plot; QVector<double> timeStamps; // 时间戳序列 QVector<QCPFinancialData> financialDatas; /* 填充时间戳和财务数据 */ ... QCPFinancial *financial = new QCPFinancial(&plot.xAxis,&plot.yAxis); financial->setData(timeStamps,financialDatas); layout->addWidget(&plot); window.setLayout(layout); window.resize(800,600); window.setWindowTitle("Simple Financial Chart Example"); window.show(); return app.exec(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值