QT 模仿QQ的截图框 支持基本的拖拉 移动 固定大小 可以复制到剪贴板和保存到文件中

QT的学习第四部分 本文介绍Qt与Linux V4L2框架下摄像头及音视频处理实现。基于Qt的QCamera与QCameraViewfinder类可便捷实现预览与拍照,需在pro文件添加multimedia和multimediawidgets插件。通过V4L2框架可深入控制摄像头参数、缓冲队列及图像采集流程,实现高精度视频捕获。结合FFmpeg与mplayer工具,可在Linux下完成音视频播放、格式转换与流媒体处理。整体涵盖从硬件接口到应用层开发的完整技术链路,适用于嵌入式多媒体系统开发。 阅读详情
#include "widget.h"
#include "InputDialog.h"
#include <QtGui>
Widget::Widget(QWidget *parent,QColor selectedColor,int quality)
    : QDialog(parent),quality(quality),sColor(selectedColor)
{

    saveAt=new QAction(tr("保存到文件"),this);
    saveAt->setIcon(QIcon(":/image/save.png"));
    saveTob=new QAction(tr("保存到剪贴板"),this);
    saveTob->setIcon(QIcon(":/image/savetob.png"));
    closeAt=new QAction(tr("退出"),this);
    closeAt->setIcon(QIcon(":/image/quit.png"));
    helpAt=new QAction(tr("使用帮助"),this);
    helpAt->setIcon(QIcon(":/image/help.png"));
    fixedSizeAt=new QAction(tr("设置固定尺寸"),this);
    fixedSizeAt->setIcon(QIcon(":/image/fixedsize.png"));
    menu=new QMenu(tr("截图菜单"),this);
    menu->setStyleSheet("background-image:url(:/image/back.png);color:white");
    menu->addAction(saveAt);
    menu->addAction(saveTob);
    menu->addSeparator();
    menu->addAction(fixedSizeAt);
    menu->addSeparator();
    menu->addAction(helpAt);
    menu->addSeparator();
    menu->addAction(closeAt);
    connect(saveAt,SIGNAL(triggered()),this,SLOT(saveImage()));
    connect(saveTob,SIGNAL(triggered()),this,SLOT(saveBoard()));
    connect(closeAt,SIGNAL(triggered()),this,SLOT(close()));
    connect(helpAt,SIGNAL(triggered()),this,SLOT(emitHelp()));
    connect(fixedSizeAt,SIGNAL(triggered()),this,SLOT(input()));
    this->setMouseTracking(true);
    leftPressed=rightPressed=runOnce=done=pull=bresize=showm=false;
    fullSize=QApplication::desktop()->size();
    this->resize(fullSize);
    this->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
    //this->hide();
    //获取了当前屏幕并存储在pixmap
    screen=new QPixmap(QPixmap::grabWindow(QApplication::desktop()->winId(),
                                           0,0,fullSize.width(),fullSize.height()));
    //新建一层朦胧屏幕
    fogPix=new QPixmap(*screen);
    QPixmap fog(fullSize.width(),fullSize.height());
    fog.fill(QColor(182,182,182,192));
    QPainter painter(fogPix);
    painter.drawPixmap(0,0,fog);
    painter.setPen(QPen(QColor(255,255,0)));
    painter.drawText(fullSize.width()/2-50,50,tr("如需使用帮助,请按F1"));
}

void Widget::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    QPen pen;
    pen.setColor(Qt::yellow);
    pen.setWidth(1);
    painter.setPen(pen);
    painter.drawPixmap(0,0,*fogPix);
    QPainter painterInfo(this);
    if(pos.tlp.x()!=pos.brp.x()&&
            pos.tlp.y()!=pos.brp.y())
    {
        QPoint zPoint(1,1);

        painterInfo.setPen(QPen(sColor));
        painterInfo.drawRect(QRect(pos.tlp-zPoint,pos.brp));
        painterInfo.drawRect(pos.tlp.x()-3,pos.tlp.y()-3,3,3);
        painterInfo.drawRect(pos.trp.x(),pos.trp.y()-3,3,3);
        painterInfo.drawRect(pos.blp.x()-3,pos.blp.y()+1,3,3);
        painterInfo.drawRect(pos.brp.x()+1,pos.brp.y()+1,3,3);

        painterInfo.drawRect((pos.tlp.x()+pos.trp.x())/2-2,
                             (pos.tlp.y()-4),3,3);
        painterInfo.drawRect(pos.tlp.x()-4,
                             (pos.tlp.y()+pos.blp.y())/2-2,3,3);
        painterInfo.drawRect(pos.trp.x()+1,
                             (pos.trp.y()+pos.brp.y())/2-2,3,3);
        painterInfo.drawRect((pos.blp.x()+pos.brp.x())/2-2,
                             pos.blp.y()+1,3,3);
        painterInfo.drawPixmap(pos.tlp,
                               screen->copy(QRect(pos.tlp,pos.brp)));
        painterInfo.setBrush(QBrush(QColor(200,200,200,165)));
        painterInfo.setPen(QPen(QColor(200,200,200,165)));
        painterInfo.drawRect(pos.tlp.x(),pos.tlp.y()>=40?
                                 pos.tlp.y()-40:pos.tlp.y(),150,40);
        painterInfo.setPen(QPen(Qt::black));
        painterInfo.drawText(pos.tlp.x()+10,
                            pos.tlp.y()>=40?pos.tlp.y()-25:pos.tlp.y()+15,
                             tr("截图开始坐标(%1,%2)").arg(QString::number(pos.tlp.x()),
                                                     QString::number(pos.tlp.y())));
        painterInfo.drawText(pos.tlp.x()+10,
                             pos.tlp.y()>=40?pos.tlp.y()-10:pos.tlp.y()+30,
                             tr("截图尺寸大小(%1,%2)").arg(QString::number(pos.brp.x()-pos.tlp.x()),
                                                     QString::number(pos.brp.y()-pos.tlp.y())));
    }
    else
    {
        cursor.setShape(Qt::ArrowCursor);
        this->setCursor(cursor);
    }
}
void Widget::mousePressEvent(QMouseEvent *e)
{
    if(e->button()==Qt::LeftButton)
    {
        leftPressed=true;
        if(!(e->globalPos().x()>pos.tlp.x()&&
             e->globalPos().y()>pos.tlp.y()&&
             e->globalPos().x()<pos.brp.x()&&
             e->globalPos().y()<pos.brp.y())&&
                !(e->globalPos().x()>=pos.tlp.x()-5&&
                  e->globalPos().x()<=pos.tlp.x()-1&&
                  e->globalPos().y()>=pos.tlp.y()-5&&
                  e->globalPos().y()<=pos.tlp.y()-1)&&
                !(e->globalPos().x()>=pos.trp.x()+1&&
                  e->globalPos().x()<=pos.trp.x()+5&&
                  e->globalPos().y()<=pos.trp.y()+1&&
                  e->globalPos().y()>=pos.trp.y()-5)&&
                !(e->globalPos().x()>=pos.blp.x()-5&&
                  e->globalPos().x()<=pos.blp.x()-1&&
                  e->globalPos().y()<=pos.blp.y()+5&&
                  e->globalPos().y()>=pos.blp.y()+1)&&
                !(e->globalPos().x()>=pos.brp.x()+1&&
                  e->globalPos().x()<=pos.brp.x()+5&&
                  e->globalPos().y()>=pos.brp.y()+1&&
                  e->globalPos().y()<=pos.brp.y()+5)&&
                !((e->globalPos().x()>=(pos.tlp.x()+pos.trp.x())/2-2&&
                   e->globalPos().x()<=(pos.tlp.x()+pos.trp.x())/2+2&&
                   e->globalPos().y()<=pos.tlp.y()-1&&
                   e->globalPos().y()>=pos.tlp.y()-4))&&
                !(e->globalPos().x()>=pos.tlp.x()-4&&
                  e->globalPos().x()<=pos.tlp.x()-1&&
                  e->globalPos().y()>=(pos.tlp.y()+pos.blp.y())/2-2&&
                  e->globalPos().y()<=(pos.tlp.y()+pos.blp.y())/2+2)&&
                !(e->globalPos().x()>=(pos.blp.x()+pos.brp.x())/2-2&&
                 e->globalPos().x()<=(pos.blp.x()+pos.brp.x())/2+2&&
                 e->globalPos().y()>=pos.blp.y()+1&&
                 e->globalPos().y()<=pos.blp.y()+4)&&
                !(e->globalPos().x()>=pos.trp.x()+1&&
                                e->globalPos().x()<=pos.trp.x()+4&&
                                e->globalPos().y()>=(pos.trp+pos.brp).y()/2-2&&
                                e->globalPos().y()<=(pos.trp+pos.brp).y()/2+2)) //不在所选的区域内
        {
            p1=e->globalPos();
            done=false;
        }
        if((e->globalPos().x()>pos.tlp.x()&&
            e->globalPos().y()>pos.tlp.y()&&
            e->globalPos().x()<pos.brp.x()&&
            e->globalPos().y()<pos.brp.y()))
        {
            pull=true;
        }
        if(e->globalPos().x()>=pos.tlp.x()-5&&
                e->globalPos().x()<=pos.tlp.x()-1&&
                e->globalPos().y()>=pos.tlp.y()-5&&
                e->globalPos().y()<=pos.tlp.y()-1)
        {
            bresize=true;
            moved=1;
        }
        if(e->globalPos().x()>=pos.trp.x()+1&&
                e->globalPos().x()<=pos.trp.x()+5&&
                e->globalPos().y()<=pos.trp.y()+1&&
                e->globalPos().y()>=pos.trp.y()-5)
        {
            bresize=true;
            moved=2;
        }
        if(e->globalPos().x()>=pos.blp.x()-5&&
                e->globalPos().x()<=pos.blp.x()-1&&
                e->globalPos().y()<=pos.blp.y()+5&&
                e->globalPos().y()>=pos.blp.y()+1)
        {
            bresize=true;
            moved=3;
        }
        if(e->globalPos().x()>=pos.brp.x()+1&&
                e->globalPos().x()<=pos.brp.x()+5&&
                e->globalPos().y()>=pos.brp.y()+1&&
                e->globalPos().y()<=pos.brp.y()+5)
        {
            bresize=true;
            moved=4;
        }
        if(e->globalPos().x()>=(pos.tlp.x()+pos.trp.x())/2-2&&
                e->globalPos().x()<=(pos.tlp.x()+pos.trp.x())/2+2&&
                e->globalPos().y()<=pos.tlp.y()-1&&
                e->globalPos().y()>=pos.tlp.y()-4)
        {
            bresize=true;
            moved=5;
        }
        if(e->globalPos().x()>=pos.tlp.x()-4&&
                e->globalPos().x()<=pos.tlp.x()-1&&
                e->globalPos().y()>=(pos.tlp.y()+pos.blp.y())/2-2&&
                e->globalPos().y()<=(pos.tlp.y()+pos.blp.y())/2+2)
        {
            bresize=true;
            moved=6;
        }
        if(e->globalPos().x()>=(pos.blp.x()+pos.brp.x())/2-2&&
                e->globalPos().x()<=(pos.blp.x()+pos.brp.x())/2+2&&
                e->globalPos().y()>=pos.blp.y()+1&&
                e->globalPos().y()<=pos.blp.y()+4)
        {
            bresize=true;
            moved=8;
        }
        if(e->globalPos().x()>=pos.trp.x()+1&&
                e->globalPos().x()<=pos.trp.x()+4&&
                e->globalPos().y()>=(pos.trp+pos.brp).y()/2-2&&
                e->globalPos().y()<=(pos.trp+pos.brp).y()/2+2)
        {
            bresize=true;
            moved=7;
        }
    }
    else if(e->button()==Qt::RightButton)
    {
        if(!(e->globalPos().x()>pos.tlp.x()&&
             e->globalPos().y()>pos.tlp.y()&&
             e->globalPos().x()<pos.brp.x()&&
             e->globalPos().y()<pos.brp.y())&&
                !(e->globalPos().x()>=pos.tlp.x()-5&&
                  e->globalPos().x()<=pos.tlp.x()-1&&
                  e->globalPos().y()>=pos.tlp.y()-5&&
                  e->globalPos().y()<=pos.tlp.y()-1)&&
                !(e->globalPos().x()>=pos.trp.x()+1&&
                  e->globalPos().x()<=pos.trp.x()+5&&
                  e->globalPos().y()<=pos.trp.y()+1&&
                  e->globalPos().y()>=pos.trp.y()-5)&&
                !(e->globalPos().x()>=pos.blp.x()-5&&
                  e->globalPos().x()<=pos.blp.x()-1&&
                  e->globalPos().y()<=pos.blp.y()+5&&
                  e->globalPos().y()>=pos.blp.y()+1)&&
                !(e->globalPos().x()>=pos.brp.x()+1&&
                  e->globalPos().x()<=pos.brp.x()+5&&
                  e->globalPos().y()>=pos.brp.y()+1&&
                  e->globalPos().y()<=pos.brp.y()+5)&&
                !(e->globalPos().x()>=(pos.tlp.x()+pos.trp.x())/2-2&&
                  e->globalPos().x()<=(pos.tlp.x()+pos.trp.x())/2+2&&
                  e->globalPos().y()<=pos.tlp.y()-1&&
                  e->globalPos().y()>=pos.tlp.y()-4)&&
                !(e->globalPos().x()>=pos.tlp.x()-4&&
                  e->globalPos().x()<=pos.tlp.x()-1&&
                  e->globalPos().y()>=(pos.tlp.y()+pos.blp.y())/2-2&&
                  e->globalPos().y()<=(pos.tlp.y()+pos.blp.y())/2+2)&&
                !(e->globalPos().x()>=(pos.blp.x()+pos.brp.x())/2-2&&
                 e->globalPos().x()<=(pos.blp.x()+pos.brp.x())/2+2&&
                 e->globalPos().y()>=pos.blp.y()+1&&
                 e->globalPos().y()<=pos.blp.y()+4)&&
                !(e->globalPos().x()>=pos.trp.x()+1&&
                                e->globalPos().x()<=pos.trp.x()+4&&
                                e->globalPos().y()>=(pos.trp+pos.brp).y()/2-2&&
                                e->globalPos().y()<=(pos.trp+pos.brp).y()/2+2)) //不在所选的区域内
        {
            this->reset();
            done=false;
            leftPressed=false;
            rightPressed=false;
            runOnce=false;
            bresize=false;
            pull=false;
            showm=false;
            this->update();
        }
        else
        {
            showm=true;
        }
    }
}
void Widget::mouseMoveEvent(QMouseEvent *e)
{
    if(leftPressed)
    {
        if(!done)
        {
            p2.setX(e->globalPos().x());
            p2.setY(e->globalPos().y());
            this->figPos(p1,p2);
            this->update();
        }
        if(bresize)
        {
            if(moved==1)
            {
                if(!runOnce)
                {
                    start=e->globalPos();
                    runOnce=true;
                }
                if(pos.tlp.x()+(e->globalPos().x()-start.x())<pos.brp.x()&&
                        pos.tlp.y()+(e->globalPos().y()-start.y())<pos.brp.y())
                {
                    pos.tlp.setX(pos.tlp.x()+(e->globalPos().x()-start.x()));
                    pos.tlp.setY(pos.tlp.y()+(e->globalPos().y()-start.y()));
                    this->figPos(pos.tlp,pos.brp);
                }
                start=e->globalPos();
                this->update();
            }
            else if(moved==2)
            {
                if(!runOnce)
                {
                    start=e->globalPos();
                    runOnce=true;
                }
                if(pos.trp.x()+(e->globalPos().x()-start.x())>pos.blp.x()&&
                        pos.trp.y()+(e->globalPos().y()-start.y())<pos.blp.y())
                {
                    pos.trp.setX(pos.trp.x()+(e->globalPos().x()-start.x()));
                    pos.trp.setY(pos.trp.y()+(e->globalPos().y()-start.y()));
                    this->figPos(pos.trp,pos.blp);
                }
                start=e->globalPos();
                this->update();
            }
            else if(moved==3)
            {
                if(!runOnce)
                {
                    start=e->globalPos();
                    runOnce=true;
                }
                if(pos.blp.x()+(e->globalPos().x()-start.x())<pos.trp.x()&&
                       pos.blp.y()+(e->globalPos().y()-start.y())>pos.trp.y())
                {
                    pos.blp.setX(pos.blp.x()+(e->globalPos().x()-start.x()));
                    pos.blp.setY(pos.blp.y()+(e->globalPos().y()-start.y()));
                    this->figPos(pos.blp,pos.trp);
                }
                start=e->globalPos();
                this->update();
            }
            else if(moved==4)
            {
                if(!runOnce)
                {
                    start=e->globalPos();
                    runOnce=true;
                }
                if(pos.brp.x()+(e->globalPos().x()-start.x())>pos.tlp.x()&&
                        pos.brp.y()+(e->globalPos().y()-start.y())>pos.tlp.y())
                {
                    pos.brp.setX(pos.brp.x()+(e->globalPos().x()-start.x()));
                    pos.brp.setY(pos.brp.y()+(e->globalPos().y()-start.y()));
                    this->figPos(pos.brp,pos.tlp);
                }
                start=e->globalPos();
                this->update();
            }
            else if(moved==5)
            {
                if(!runOnce)
                {
                    start=e->globalPos();
                    runOnce=true;
                }
                if(pos.tlp.y()+(e->globalPos().y()-start.y())<pos.blp.y())
                {
                    pos.tlp.setY(pos.tlp.y()+(e->globalPos().y()-start.y()));
                    this->figPos(pos.tlp,pos.brp);
                }
                start=e->globalPos();
                this->update();
            }
            else if(moved==6)
            {
                if(!runOnce)
                {
                    start=e->globalPos();
                    runOnce=true;
                }
                if((pos.tlp.x()+(e->globalPos()-start).x())<pos.brp.x())
                {
                    pos.tlp.setX(pos.tlp.x()+(e->globalPos().x()-start.x()));
                    this->figPos(pos.tlp,pos.brp);
                }
                start=e->globalPos();
                this->update();
            }
            else if(moved==8)
            {
                if(!runOnce)
                {
                    start=e->globalPos();
                    runOnce=true;
                }
                if(pos.blp.y()+(e->globalPos().y()-start.y())>pos.tlp.y())
                {
                    pos.blp.setY(pos.blp.y()+(e->globalPos().y()-start.y()));
                    this->figPos(pos.blp,pos.trp);
                }
                start=e->globalPos();
                this->update();
            }
            else if(moved=7)
            {
                if(!runOnce)
                {
                    start=e->globalPos();
                    runOnce=true;
                }
                if((pos.trp.x()+(e->globalPos()-start).x())>pos.blp.x())
                {
                    pos.trp.setX(pos.trp.x()+(e->globalPos().x()-start.x()));
                    this->figPos(pos.trp,pos.blp);
                }
                start=e->globalPos();
                this->update();
            }
        }
        if(pull)
        {
            if(!runOnce)
            {
                start=e->globalPos();
                runOnce=true;
            }
            if(pos.tlp.x()+e->globalPos().x()-start.x()>0&&
                    pos.tlp.x()+e->globalPos().x()-start.x()<=fullSize.width()&&
                    pos.tlp.y()+e->globalPos().y()-start.y()>0&&
                    pos.tlp.y()+e->globalPos().y()-start.y()<=fullSize.height()&&
                    pos.brp.x()+e->globalPos().x()-start.x()>=0&&
                    pos.brp.x()+e->globalPos().x()-start.x()<fullSize.width()&&
                    pos.brp.y()+e->globalPos().y()-start.y()>=0&&
                    pos.brp.y()+e->globalPos().y()-start.y()<=fullSize.height())
            {
                pos.tlp+=(e->globalPos()-start);
                pos.brp+=(e->globalPos()-start);
                this->figPos(pos.tlp,pos.brp);
            }
            else if(pos.tlp.x()+e->globalPos().x()-start.x()<=0&&
                    pos.blp.y()+e->globalPos().y()-start.y()<=fullSize.height()&&
                    pos.tlp.y()+e->globalPos().y()-start.y()>=0)//左边
            {
                pos.tlp.setX(0);
                pos.tlp.setY(pos.tlp.y()+e->globalPos().y()-start.y());
                pos.brp.setX(pos.brp.x()-pos.blp.x());
                pos.brp.setY(pos.brp.y()+e->globalPos().y()-start.y());
                this->figPos(pos.tlp,pos.brp);
            }
            else if(pos.tlp.y()+e->globalPos().y()-start.y()<=0&&
                    pos.tlp.x()+e->globalPos().x()-start.x()>=0&&
                    pos.trp.x()+e->globalPos().x()-start.x()<=fullSize.width())//上
            {
                pos.tlp.setY(0);
                pos.tlp.setX(pos.tlp.x()+e->globalPos().x()-start.x());
                pos.brp.setX(pos.brp.x()+e->globalPos().x()-start.x());
                pos.brp.setY(pos.tlp.y()+pos.blp.y()-pos.trp.y());
                this->figPos(pos.tlp,pos.brp);
            }
            else if(pos.brp.x()+e->globalPos().x()-start.x()>=fullSize.width()&&
                    pos.trp.y()+e->globalPos().y()-start.y()>=0&&
                    pos.brp.y()+e->globalPos().y()-start.y()<=fullSize.height())//右
            {
                pos.brp.setX(fullSize.width());
                pos.brp.setY(pos.brp.y()+e->globalPos().y()-start.y());
                pos.tlp.setX(fullSize.width()-(pos.trp.x()-pos.blp.x()));
                pos.tlp.setY(pos.tlp.y()+e->globalPos().y()-start.y());
                this->figPos(pos.tlp,pos.brp);
            }
            else if(pos.brp.y()+e->globalPos().y()-start.y()>=fullSize.height()&&
                    pos.brp.x()+e->globalPos().x()-start.x()<=fullSize.width()&&
                    pos.blp.x()+e->globalPos().x()-start.x()>=0)//下
            {
                pos.brp.setY(fullSize.height());
                pos.brp.setX(pos.brp.x()+e->globalPos().x()-start.x());
                pos.tlp.setX(pos.tlp.x()+e->globalPos().x()-start.x());
                pos.tlp.setY(pos.brp.y()-(pos.blp.y()-pos.trp.y()));
                this->figPos(pos.tlp,pos.brp);
            }
            start=e->globalPos();
            this->update();
        }

    }
    else
    {
        if(e->globalPos().x()>=pos.tlp.x()-5&&
                e->globalPos().x()<=pos.tlp.x()-1&&
                e->globalPos().y()>=pos.tlp.y()-5&&
                e->globalPos().y()<=pos.tlp.y()-1)
        {
            cursor.setShape(Qt::SizeFDiagCursor);
            this->setCursor(cursor);
        }
        else if((e->globalPos().x()>pos.tlp.x()&&
                 e->globalPos().y()>pos.tlp.y()&&
                 e->globalPos().x()<pos.brp.x()&&
                 e->globalPos().y()<pos.brp.y()))
        {
            cursor.setShape(Qt::SizeAllCursor);
            this->setCursor(cursor);
        }
        else if(e->globalPos().x()>=pos.trp.x()+1&&
                e->globalPos().x()<=pos.trp.x()+5&&
                e->globalPos().y()<=pos.trp.y()+1&&
                e->globalPos().y()>=pos.trp.y()-5)
        {
            cursor.setShape(Qt::SizeBDiagCursor);
            this->setCursor(cursor);
        }
        else if(e->globalPos().x()>=pos.blp.x()-5&&
                e->globalPos().x()<=pos.blp.x()-1&&
                e->globalPos().y()<=pos.blp.y()+5&&
                e->globalPos().y()>=pos.blp.y()+1)
        {
            cursor.setShape(Qt::SizeBDiagCursor);
            this->setCursor(cursor);
        }
        else if(e->globalPos().x()>=pos.brp.x()+1&&
                e->globalPos().x()<=pos.brp.x()+5&&
                e->globalPos().y()>=pos.brp.y()+1&&
                e->globalPos().y()<=pos.brp.y()+5)
        {
            cursor.setShape(Qt::SizeFDiagCursor);
            this->setCursor(cursor);
        }
        else if(e->globalPos().x()>=(pos.tlp.x()+pos.trp.x())/2-2&&
                e->globalPos().x()<=(pos.tlp.x()+pos.trp.x())/2+2&&
                e->globalPos().y()<=pos.tlp.y()-1&&
                e->globalPos().y()>=pos.tlp.y()-4)
        {
            cursor.setShape(Qt::SizeVerCursor);
            this->setCursor(cursor);
        }
        else if(e->globalPos().x()>=pos.tlp.x()-4&&
                e->globalPos().x()<=pos.tlp.x()-1&&
                e->globalPos().y()>=(pos.tlp.y()+pos.blp.y())/2-2&&
                e->globalPos().y()<=(pos.tlp.y()+pos.blp.y())/2+2)
        {
            cursor.setShape(Qt::SizeHorCursor);
            this->setCursor(cursor);
        }
        else if(e->globalPos().x()>=(pos.blp.x()+pos.brp.x())/2-2&&
                e->globalPos().x()<=(pos.blp.x()+pos.brp.x())/2+2&&
                e->globalPos().y()>=pos.blp.y()+1&&
                e->globalPos().y()<=pos.blp.y()+4)
        {
            cursor.setShape(Qt::SizeVerCursor);
            this->setCursor(cursor);
        }
        else if(e->globalPos().x()>=pos.trp.x()+1&&
                e->globalPos().x()<=pos.trp.x()+4&&
                e->globalPos().y()>=(pos.trp+pos.brp).y()/2-2&&
                e->globalPos().y()<=(pos.trp+pos.brp).y()/2+2)
        {
            cursor.setShape(Qt::SizeHorCursor);
            this->setCursor(cursor);
        }
        else
        {
            QCursor cursor;
            cursor.setShape(Qt::ArrowCursor);
            this->setCursor(cursor);
        }

    }

    if(rightPressed)
    {

    }
}
void Widget::mouseReleaseEvent(QMouseEvent *e)
{
    leftPressed=false;
    runOnce=false;
    done=true;
    bresize=false;
    pull=false;
    if(e->button()==Qt::RightButton)
    {
        if(!(e->globalPos().x()>pos.tlp.x()&&
             e->globalPos().y()>pos.tlp.y()&&
             e->globalPos().x()<pos.brp.x()&&
             e->globalPos().y()<pos.brp.y())&&
                !(e->globalPos().x()>=pos.tlp.x()-5&&
                  e->globalPos().x()<=pos.tlp.x()-1&&
                  e->globalPos().y()>=pos.tlp.y()-5&&
                  e->globalPos().y()<=pos.tlp.y()-1)&&
                !(e->globalPos().x()>=pos.trp.x()+1&&
                  e->globalPos().x()<=pos.trp.x()+5&&
                  e->globalPos().y()<=pos.trp.y()+1&&
                  e->globalPos().y()>=pos.trp.y()-5)&&
                !(e->globalPos().x()>=pos.blp.x()-5&&
                  e->globalPos().x()<=pos.blp.x()-1&&
                  e->globalPos().y()<=pos.blp.y()+5&&
                  e->globalPos().y()>=pos.blp.y()+1)&&
                !(e->globalPos().x()>=pos.brp.x()+1&&
                  e->globalPos().x()<=pos.brp.x()+5&&
                  e->globalPos().y()>=pos.brp.y()+1&&
                  e->globalPos().y()<=pos.brp.y()+5))
        {}
        else
        {
            if(showm)
            {
                menu->exec(e->globalPos());
            }
        }
    }
    rightPressed=false;
    showm=false;
    //cursor.setShape(Qt::ArrowCursor);
    //this->setCursor(cursor);
}
void Widget::keyPressEvent(QKeyEvent *e)
{
    switch(e->key())
    {
    case Qt::Key_Left:
        if(pos.tlp.x()-1>=0)
        {
            pos.tlp.setX(pos.tlp.x()-1);
            pos.brp.setX(pos.brp.x()-1);
        }
        break;
    case Qt::Key_Right:
        if(pos.blp.x()+1<=fullSize.width())
        {
            pos.tlp.setX(pos.tlp.x()+1);
            pos.brp.setX(pos.brp.x()+1);
            this->figPos(pos.tlp,pos.brp);
        }
        break;
    case Qt::Key_Up:
        if(pos.tlp.y()-1>=0)
        {
            pos.tlp.setY(pos.tlp.y()-1);
            pos.brp.setY(pos.brp.y()-1);
            this->figPos(pos.tlp,pos.brp);
        }
        break;
    case Qt::Key_Down:
        if(pos.brp.y()+1<=fullSize.height())
        {
            pos.tlp.setY(pos.tlp.y()+1);
            pos.brp.setY(pos.brp.y()+1);
            this->figPos(pos.tlp,pos.brp);
        }
        break;
    case Qt::Key_Enter:
        this->saveImage();
        break;
    case Qt::Key_Escape:
        this->close();
        this->destroy();
        emit closed();
        break;
    case Qt::Key_Space:
        this->saveBoard();
    default:
        break;
    }
    this->update();
}
void Widget::saveImage()
{
    QString slcStr;
    QPoint end=pos.brp;
    end.setX(end.x()-1);
    end.setY(end.y()-1);
    fileName=QFileDialog::getSaveFileName(this,tr("保存截图"),
                                              "c:/untitled.png",
                                              tr("PNG(*.png);;JPG(*.jpg);;BMP(*.bmp)"),&slcStr);
    if(slcStr.left(3)=="JPG")
    {
        if(fileName.right(3)!="jpg")
        {
            fileName+=".jpg";
        }
    }
    if(slcStr.left(3)=="PNG")
    {
        if(fileName.right(3)!="png")
        {
            fileName+=".png";
        }
    }
    if(slcStr.left(3)=="BMP")
    {
        if(fileName.right(3)!="bmp")
        {
            fileName+=".bmp";
        }
    }
    if(!fileName.isEmpty())
    {
        file=new QFile(fileName);
    }
    else
        return;
    QFileInfo fileInfo(fileName);
    QString ext=fileInfo.suffix();
    if(file->open(QIODevice::WriteOnly))
    {
        screen->copy(QRect(pos.tlp,end)).save(file,ext.toStdString().c_str(),quality);
        qDebug()<<ext;
        file->close();
    }
    delete file;
    this->close();
}
void Widget::saveBoard()
{
    QApplication::clipboard()->setImage(screen->copy(QRect(pos.tlp,pos.brp)).toImage());
    this->close();
}
void Widget::reset()
{
    QPoint zeroP(0,0);
    pos.blp=zeroP;
    pos.brp=zeroP;
    pos.tlp=zeroP;
    pos.trp=zeroP;
}
void Widget::figPos(const QPoint& p1,const QPoint& p2)
{
    if(p1.x()<p2.x()&&
            p1.y()<p2.y())
    {
        pos.tlp=p1;
        pos.trp.setX(p2.x());
        pos.trp.setY(p1.y());
        pos.blp.setX(p1.x());
        pos.blp.setY(p2.y());
        pos.brp=p2;
    }
    else if(p1.x()>p2.x()&&
            p1.y()<p2.y())
    {
        pos.tlp.setX(p2.x());
        pos.tlp.setY(p1.y());
        pos.trp=p1;
        pos.blp=p2;
        pos.brp.setX(p1.x());
        pos.brp.setY(p2.y());
    }
    else if(p1.x()<p2.x()&&
            p1.y()>p2.y())
    {
        pos.tlp.setX(p1.x());
        pos.tlp.setY(p2.y());
        pos.trp=p2;
        pos.brp=p1;
        pos.brp.setX(p2.x());
        pos.brp.setY(p1.y());
    }
    else if(p1.x()>p2.x()&&
            p1.y()>p2.y())
    {
        pos.tlp=p2;
        pos.trp.setX(p1.x());
        pos.trp.setY(p2.y());
        pos.blp.setX(p2.x());
        pos.blp.setY(p1.y());
        pos.brp=p1;
    }
}
void Widget::mouseDoubleClickEvent(QMouseEvent *e)
{
    if(e->button()==Qt::LeftButton&&
            (e->globalPos().x()>pos.tlp.x()&&
             e->globalPos().y()>pos.tlp.y()&&
             e->globalPos().x()<pos.brp.x()&&
             e->globalPos().y()<pos.brp.y()))
    {
        this->saveBoard();
    }
}
void Widget::emitHelp()
{
    emit showHelp();
}
void Widget::keyReleaseEvent(QKeyEvent *e)
{
    switch(e->key())
    {
    case Qt::Key_F1:
        emit emitHelp();
        break;
    default:
        QDialog::keyReleaseEvent(e);
        break;
    }
}
void Widget::setMySize(int n1, int n2)
{
    if(n1!=0)
    {
        if(pos.tlp.x()+n1>=fullSize.width())
        {
            pos.brp.setX(fullSize.width());
        }
        else
        {
            pos.brp.setX(pos.tlp.x()+n1);
        }
        this->figPos(pos.tlp,pos.brp);
        this->update();
    }
    if(n2!=0)
    {
        if(pos.tlp.y()+n2>=fullSize.height())
        {
            pos.brp.setY(fullSize.height());
        }
        else
        {
            pos.brp.setY(pos.tlp.y()+n2);
        }
        this->figPos(pos.tlp,pos.brp);
        this->update();
    }
}
void Widget::input()
{
    InputDialog id(0);
    connect(&id,SIGNAL(input(int,int)),this,SLOT(setMySize(int,int)));
    id.exec();
}

 

#ifndef WIDGET_H
#define WIDGET_H

#include <QtGui/QDialog>
#include <QSize>
#include <QPoint>
#include <QCursor>
#include <QColor>
class QFile;
class QPixmap;
class QMenu;
class QAction;
class Widget : public QDialog
{
    Q_OBJECT

public:
    struct posInfo
    {
        QPoint tlp,
                trp,
                blp,
                brp;
    };
    QPoint p1,p2;
    Widget(QWidget *parent = 0,QColor selectedColor=QColor(0,0,255),int quality=-1);
    ~Widget(){delete screen;delete fogPix;}
    void reset();
private:
    QPixmap *screen,
            *fogPix;
    posInfo pos;
    bool rightPressed,
        leftPressed,
        done,
        pull;
    int moved;
    bool runOnce;
    bool bresize;
    bool showm;
    QColor sColor;
    QPoint start;
    QString fileName;
    QFile *file;
    QSize fullSize;
    QCursor cursor;
    QMenu *menu;
    QAction *saveAt,
            *closeAt,
            *saveTob,
            *helpAt,
            *fixedSizeAt;
    int quality;

    void figPos(const QPoint&,const QPoint&);
protected:
    void paintEvent(QPaintEvent *);
    void mousePressEvent(QMouseEvent *);
    void mouseMoveEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);
    void keyPressEvent(QKeyEvent *);
    void mouseDoubleClickEvent(QMouseEvent *);
    void keyReleaseEvent(QKeyEvent *);
private slots:
    void saveImage();
    void saveBoard();
    void emitHelp();
    void setMySize(int,int);
    void input();
signals:
    void closed();
    void showHelp();
};

#endif // WIDGET_H



其中其它的对话框可以都删掉

 

效果图如下

机器学习——笔记整理(原理、python代码)——反反复复,出精活! 回顾知识,检查自我,开拓新域。 机器学习1.监督学习 机器学习简介: 机器学习是实现人工智能的手段,其主要研究内容是如何利用数据或经验进行学习,改善具体算法的性能。 多领域交叉,涉及概率论、统计学,算法复杂度理论等多门学科 广泛应用于网络搜索、垃圾邮件过滤、推荐系统、广告投放、信用评价、欺诈检测、股票交易和医疗诊断等应用。 机器学习分类: 机器学习一般分为下面几种类别 监督学习 ( Supervised Learning) 无监督学习 ( Unsupervised Learning) 强化学习( 阅读详情

相关推荐

从零到一:如何用YOLOv8和PyQt5打造一个高效的路面坑洞检测系统

本文详细介绍了如何利用YOLOv8和PyQt5开发一个高效的路面坑洞检测系统。从环境配置、数据采集标注到模型训练优化,再到PyQt5界面开发与系统集成,提供了完整的实战指南。该系统结合深度学习技术,显著提升了道路检测的准确性和效率,适用于各类道路维护场景。

weixin_29047919的博客 308

Qt实现截图(可移动截屏区域并修改大小)

可以显示截图区域大小,可以任意拖动截图区域,四个边框可拖拽修改大小

weixin_46246664的博客 2010

qt 截屏工具Qscreen Qpixmap

要想在Qt中实现屏幕或窗口截图功能 ,通常有两种方法:   1  -- 使用 QPixmap 类   2  -- 使用 QScreen类 然而虽然俩两种方法用到的类不相同,但是调用到的类成员函数的函数名称和参数却是相同的 都是 grabWindow() 这个函数 所不同的是,QPixmap中的 grabWindow()函数 是静态成员 QScreen中的

linux 9316

大红球预警版-精选+自定义板块监控

这是一款简单易用的股票大单资金监控插件,兼容通达信软件,可嵌入分时图或定制版面。它以红绿圆球直观显示主力买卖情况(红球为买,绿球为卖),支持300万以上大单语音播报。插件提供实时资金流向分析、多股同时监控、自定义预警条件等功能,无需L2账号。用户可自由切换图形/列表模式,监控特定板块,并配合幻影软件实现自动交易。虽然上涨股通常红球占优,但需结合其他指标综合判断。该插件完全免费,包含详细视频教程,适合新手使用。

guleba的博客 1793

模拟CMOS 第2章 MOS器件物理基础

模拟CMOS 第2章 MOS器件物理基础 文章目录模拟CMOS 第2章 MOS器件物理基础2.1 基本概念2.1.1 MOSEFT开关2.1.2 MOSEFT结构2.1.3 MOS符号2.2 MOS的I/V特性2.2.1 阈值电压2.2.2 I/V特性的推导2.3 二级效应2.4 MOS器件模型2.4.1 MOS器件版图2.4.2 MOS器件电容2.4.3 MOS小信号模型2.4.4 MOS SPICE模型2.4.5 NMOS与PMOS器件的比较2.4.6 长沟道器件与短沟道器件的比较附录A 用作电容器MO

椰子奶糖的博客 5199

QT做类似QQ截图功能(带图片编辑功能)

这里采用的方法是按下截屏按钮截取整个桌面,然后通过鼠标的拖动选中截取的区域,并把这个区域用截取的那张大图中相应的位置设置为QLabel背景,其他的保存或者完成等操作通过按钮的响应来完成。值得说的就是这个是有类似QQ的那种截图编辑功能,支持曲线,矩形,圆,编辑文字。至于那个类似QQ的箭头功能暂时还没有实现,已经有了思路,后续补上。 好的,上代码: class ScreenShot : public Q

战神无悔的专栏 6270

协方差矩阵

对两个类内协方差矩阵进行对角化,可以将它们变换为对角矩阵。这个过程可以通过对每个协方差矩阵进行特征值分解来实现,从而得到它们的特征向量和特征值,进而得到它们的对角矩阵形式。这个过程的意义在于,它可以帮助我们找到一个新的坐标系,使得在这个坐标系下,每个特征之间都是独立的,从而简化了计算。具体来说,当我们使用对角协方差矩阵作为特征向量的坐标系时,它意味着每个特征之间都是相互独立的,从而方便了进一步的分析和处理。在实际应用中,对角化协方差矩阵可以用于降维、特征选择和分类等任务。

m0_55196097的博客 1万+

如何把截图固定在电脑页面上

如果我们给人讲网课课,或者汇报的时候想把公式,定理,图片等放在醒目位置做对比。那么我们可能需要把截图放在别的文件的页面上,那么我们要怎么做呢? 方法一: 利用QQ截图功能 1.先登录QQ,不然不能使用QQ截图功能 2.使用QQ快捷键( ctrl + alt + a )截图,截图后有个“钉在桌面上”的按钮,点击一下即可 3.钉在桌面后,可以打开自己想用的文件 4.如果不想要了,直接打“x”即可关闭 方法二: 使用Snipaste软件 网盘可下载: 链接:https://pan.b.

ggj0727的博客 11万+

从爆仓到流畅发货:我们如何用EIQ分析给跨境小电商仓库做了一次‘体检’与‘手术’

本文分享了如何通过EIQ分析工具为跨境小电商仓库进行诊断与优化,从爆仓危机到流畅发货的实战经验。通过ABC分类法、动态路径算法等策略,拣货效率提升40%,错发率降低91%,日均处理能力翻倍。文章为小电商提供了轻量级工具选择和关键指标监控的实用建议。

weixin_28707739的博客 397

C#国产化技术路线(全栈落地指南,适配信创场景)

本文详细介绍了C#语言在信创产业中的国产化适配方案。核心方案基于.NET8框架,通过硬件架构适配、基础软件替换和打包部署优化三个层面进行改造,无需更换开发语言即可适配国产CPU和操作系统。文章系统讲解了开发工具选择、全栈适配层改造、数据库替换等技术要点,并提供了桌面应用和服务端应用的具体开发流程。针对政务、金融、能源等典型场景给出了可直接套用的技术组合,同时总结了10个关键避坑点。该方案可复用C#开发特性,实现低成本迁移,已在多个行业成功落地。

weilinc的专栏 1198

一款支持固定区域,固定尺寸大小重复截图的软件

WinSnap是一款功能强大的屏幕截图软件,可以实现对固定区域,固定尺寸大小区域重复截图,适用于日常截图需求和专业用户进行屏幕截图和图像编辑。它还支持自定义捕捉前延时和捕捉热键,方便用户根据自己的需求进行设置。WinSnap的使用非常方便,运行界面中直接设置了屏幕捕捉常用功能和一些图像效果选项,如捕捉类别、被捕捉的图像的输出方式、颜色、阴影效果等。WinSnap是一款小巧易用且功能强大的屏幕截图软件,适用于各种截图需求,并提供了丰富的编辑功能和自定义选项,使用户能够轻松捕捉和编辑屏幕截图。

ITdgr的博客 3628

【清华大学软院】15-19年推免试题历年整理

整理的题目为清软预推免机试(外校)硕士机考题目。 年代 题目1 题目2 题目3 2019 质因数分解 二叉搜索树 区间DP(折叠字符串) 2018 日期转换 高精度模拟 区间DP(戳气球) 2017 进制素数 被遗漏的数字 DP(收集苹果) 2016 大数运算 DP DFS 2015 进制素数: http://acm.hdu.edu.cn/showproblem.php?pid=1230 2017年题目(这个是找的最准确的题目): 1题见【链接】 2题见【链接】

云端筑梦师 2255

QT 实现简单截图功能

QT 实现简单截图功能 代码内容完善、有详细的代码注释所以不在赘述。 头文件CaptureScreen.h #ifndef CAPTURESCREEN_H #define CAPTURESCREEN_H #include <QWidget> #include <QPainter> enum CaptureState{ initCapture, beginCaptureImage, finishCaptureImage, beginMoveCaptureArea,

间接性踌躇满志,持续性混吃等死。 813

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

在QT4中处理windows消息

为了能处理某些qt无法处理的事件,或者在Qt将消息封装之前能做某些操作等等,我们可以自己处理windows事件。 处理windows事件是重写QApplication::winEventFilter(MSG*,long)函数来实现的。假如我们想捕获所有在窗体上的鼠标中键按下的消息,我们可以继承一下QApplication类: class MyApplication:public QApplic

sryan的专栏 1万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

QT 新手练习 模仿系统自带 记事本

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include class QAction; class QTextEdit; class QLabel; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0);

sryan的专栏 6167

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Qt流缓冲的刷新时间小解

今天用QTextStream时候遇到了点点小问题,就是在写入的时候,发现移动文件指针不会覆盖后面的数据。今天一天的时间基本上都放在了这个问题上面,下面具体说说。 例如下面的例子 QFile file(“c:/1.txt”); QTextStream text(&file); file.open(QFile::Write); text text.device().seek(0); te

sryan的专栏 5329

关于Qt使用QSqlQuery执行sql语句时出现out of memory的问题

今天应老师要求修改数据库部分时,突然执行sql语句时候用lasterror()提示out of memory,可是我几乎什么都没改动,百思不得其解。 后来发现居然是定义QSqlQuery的前面database没有打开。只要在定义QSqlQuery的前面open database就可以了。

sryan的专栏 3605

QWT6.0.1 配置方法 使用心得

今天装了个qwt,安装装了一上午,无语啊。 首先打开qwt.pro,编译一下,然后会出现个lib文件夹,把几个dll拷贝到qt安装目录/bin/文件夹下,再把几个lib文件拷贝到lib文件夹下,再把src文件夹拷贝到include文件夹下就可以了。 然后要用的时候,把pro文件加入 DEFINES    += QT_DLL QWT_DLL CONFIG(debug,debug|releas

sryan的专栏 2309

对于Qt:QTableWidget常见属性以及QTableWidgetItem类的解析

本文详细介绍了Qt中的QTableWidget控件和QTableWidgetItem类,它们是处理二维表格数据的核心组件。主要内容包括: QTableWidgetItem类详解: 核心方法:row()/column()获取位置,setText()/text()设置文本,setIcon()设置图标 样式控制:setTextAlignment()对齐方式,setFont()字体,setSizeHint()尺寸 QTableWidget核心操作: 单元格管理:item()获取单元格,setItem()设置单元格

2503_92929084的博客 102

Qt QBuffer 详解:内存缓冲区读写与实战用法

QBuffer 是 Qt 中用于内存缓冲区读写的 QIODevice 实现,可将 QByteArray 作为“文件”进行随机访问。它支持 open()、read()、write()、seek() 等操作,常用于数据序列化(配合 QDataStream)、内存加载图片、适配仅接受 QIODevice* 的 API。使用时需注意:必须先 open(),写后需 seek(0) 才能读取;若传入外部 QByteArray,其生命周期须长于 QBuffer。适用于小到中等规模内存数据处理,大文件应避免使用。

本博客分享软硬件一体化开发实战。硬件涵盖 PCB 设计、STM32 等 MCU 底层开发;软件包含 C++、Rust,Qt/QML、PyQt、Slint、TouchGFX、LVGL 各类 GUI 框架。方便软硬件开发者查阅学习。欢迎关注! 550

Qt_03界面类型

Qt的界面类型

u012660296的博客 190

Qt 内嵌页面能显示、按钮调用桌面功能时报 Qt6WebChannel.dll?查桥接层

Qt 桌面程序里的内嵌 HTML 面板能显示静态内容,但点击“读取本地任务”才报 Qt6WebChannel.dll。先保存构建清单,用脱敏测试任务重现;页面能加载不等于 JavaScript 与 C++ 的桥接层也完整。应先确认准确弹窗,再排查模块和页面脚本。 ## Qt6WebChannel.dll 的来源与桥接组件版本 查看发行包里 Qt6Core.d

2301_78581598的博客 204

【Qt】系统相关:UDP 回显服务器

🎬 艾莉丝的简介:QUdpSocket 封装 UDP 套接字描述符,基于 Qt 信号槽机制实现事件驱动 I/O,默认走非阻塞模型。QNetworkDatagram 表示一个完整 UDP 数据报,封装载荷数据、源/目的 IP 与源/目的端口。端口号为 16 位无符号整数,取值范围 0–65535,按 IANA 划分为四段。必须引入 network 模块,否则编译器无法定位 QUdpSocket 头文件。 引入模块后仍提示找不到头文件:执行 qmake 重新解析 .pro,触发工程重新构建。 2.0.2

艾莉丝努力练剑的博客,感谢大家一直以来的对艾莉丝的支持和鼓励,uu们如果对C/C++方向感兴趣的话,可以通过艾莉丝主页的微信名片加艾莉丝的好友,和努力练剑的艾莉丝一起加油! 600

Windows/Linux下强实时运动控制内核(二):基于Qt的Delta机械手的开发应用

强实时运动控制内核MotionRT750下Qt开发Delta机械手的完整开发流程。

weixin_57350300的博客 241
上一篇: Qt流缓冲的刷新时间小解
下一篇: 在QT4中处理windows消息
碎炎
博客等级 码龄16年 85粉丝 61原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值