Реклама

Тег → QWidget

  • Troffe
  • Вопрос
  • 6 июня 2017 г. 17:01

Что выбрать?

Qt, QML, QWidget

Допустим я хочу реализовать подобный интерфейс что мне использовать QML или QWidget?

  • EVILEG
  • Статья
  • 25 апреля 2017 г. 22:23

Qt/C++ - Урок 063. Добавление окон внутри главного окна приложения с помощью QMdiArea

QMdiArea, QWidget, Qt

Многие приложения, наподобие фотошопа умеют открывать проекты (изображения, тексты и т.д.) внутри окон, которые открываются внутри основного окна приложения. Qt предоставляет подобный фукционал в виде класса QMdiArea. В объект данного класса можно помещать объекты классов, наследованных от класса QWidget , и соответственно класса QWidget. Эти объекты будут отображать как окна, только будут расположены внутри QMdiArea.

Посмотрим пример с окном внутри окна.

  • born66613
  • Вопрос
  • 15 марта 2017 г. 6:15

Проблема при перерисовке сцены - "скакание" элементов сцены по вертикали

QGraphicsView, QGraphicsScene, QWidget

Здравствуйте. Использую Qt 5.6.1.
В общем, имеется клиентское приложение, которое связывается с сервером, получает от него данные - координаты узлов сети системы управления и данные с них, и отрисовывает местоположение узлов на QGraphicsView. На сцене рисую координатную сетку, которое можно "зуммировать" колесиком мыши, "скролить" правой кнопкой мыши. Возникает интересная вещь - при скроллинге по горизонтали все отлично, при скроллинге по вертикали начинают скакать горизонтальные линии координатной сетки, подписи к оси Х. Такое ощущение, что выключена какая нибудь "вертикальная привязка" или еще что-то в этом роде. Ничего похожего в интернете не нашел.
Выкладываю 2 класса - главного окна (myclient.h, myclient.cpp) и виджета, на котором происходит рисование (mygraphicview.cpp, mygraphicview.h).
Также для лицезрения сего чуда прикрепляю папку с проектом - сначала сделайте Zoom колесиком мыши и попробуйте правой кнопкой мыши поскроллить. Увидите, что горизонтальная линия зеленого цвета начнем прыгать то в одну сторону, то в другую (в зависимости от направления скролла).
p.s. При компиляции укажите путь к БД (database.cpp).

myclient.h

#ifndef MYCLIENT_H
#define MYCLIENT_H

#include <QMainWindow>
#include <QTcpSocket>
#include <QGraphicsScene>
#include <QLabel>
#include <QStatusBar>
#include <database.h>
#include <stdlib.h>
#include <QSqlTableModel>
#include <QMessageBox>
#include <mypoint.h>
#include "mygraphicview.h"
#include <QKeyEvent>
#include <QProgressBar>

namespace Ui {
class MyClient;
}
class MyClient : public QMainWindow
{
    Q_OBJECT

public:
    explicit MyClient(QWidget *parent = 0);
    ~MyClient();
    Ui::MyClient *ui;

private:
    QProgressBar *pBar;
    MyPoint *point;
    QTcpSocket* pTcpSocket;             // Объявляем сокет
    bool Connect = false;               // Объявляем переменную, отвечающую за наличие соединения
    QGraphicsScene  *scene;             // Объявляем графическую сцену
    MyGraphicView   *myPicture;         // Наш кастомный виджет
    DataBase        *db;                // Объявляем переменную для доступа к БД
    QSqlTableModel  *model;             // Объект для взаимодействия с моделью представления таблицы БД
    // Объявяем метод для парсинга входящего сообщения
    void parsingRecMsg(const QString &RecMsg);
    // Метод для формирования модели представления таблицы БД
    void setupModel(const QString &tableName, const QStringList &headers);
    // Метод для отрисовки медели представления таблицы БД
    void createModel();
    //QLabel *mouseTracker;

protected:
    //void mouseMoveEvent(QMouseEvent* pe);
    QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const;

signals:
    void signalRepaint();

private slots:
    void slotReadyRead();
    void slotError(QAbstractSocket::SocketError);
    void slotConnected();
    void slotDisconnected();
    void on_Button_Connect_clicked();
    void on_Button_Send_clicked();


    void on_Button_AddNode_clicked();

public slots:
    void slotSelectRow(int idRow);
};

#endif // MYCLIENT_H

myclient.cpp
#include "myclient.h"
#include "ui_myclient.h"

// Конструктор:
MyClient::MyClient(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MyClient)
{
    qDebug()<<"startMakeUI";
    ui->setupUi(this);
    this->resize(732,694);                                                  // Задаем размеры окна
    this->setFixedSize(732,694);                                            // Фиксируем размеры окна
    ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);   // Отключаем скроллбар по вертикали
    ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Отключаем скроллбар по горизонтали
    this->setWindowTitle("Monitoring control system");
    // Подключаемся к БД:
    db = new DataBase();
    db->connectToDataBase();
    //this->setMouseTracking(true);
    // Инициализируем виджет с графикой
    myPicture = new MyGraphicView();
    // и добавляем его на слой
    scene = new QGraphicsScene();                                           // Инициализируем графическую сцену
    ui->graphicsView->setScene(scene);                                      // Устанавливаем графическую сцену в graphicsView
    scene->addWidget(myPicture);
    /*/ Для отображения координат указателя мыши в StatusBar
    mouseTracker = new QLabel(this);
    statusBar()->addWidget(mouseTracker);*/
    connect(this,&MyClient::signalRepaint, myPicture, &MyGraphicView::slotAlarmTimer);
    connect(myPicture,&MyGraphicView::signalSelectRow,this,&MyClient::slotSelectRow);
    // Инициализируем модель для представления данных с заданием названий колонок
    this->setupModel(TABLE, QStringList() << trUtf8("NodeID")
                                          << trUtf8("Х")
                                          << trUtf8("Y")
                                          << trUtf8("Z")
                                          << trUtf8("Data 1")
                                          << trUtf8("Data 2")
                                          << trUtf8("Data 3")
                                          << trUtf8("State"));
    this->createModel();
}

// Диструктор:
MyClient::~MyClient()
{
    qDebug()<<"startDeleteUI";
    delete ui;
}

// Обработчик нажатия кнопки Connect:
void MyClient::on_Button_Connect_clicked()
{
    qDebug()<<"on_Button_Connect_clicked()";
    if (Connect==false){ // если соединения нет
        qDebug()<<"on_Button_Connect_clicked(): connecting...";
        bool PortNumber_ok;
        const QString IP = this->ui->LEdit_IPAdress->text();
        const ushort port = this->ui->LEdit_PortNumber->text().toUShort(&PortNumber_ok);
        if (!PortNumber_ok)
        {
            QMessageBox msgBox;
            msgBox.setText("The port is not valid.");
            msgBox.exec();
            return;
        }
        pTcpSocket = new QTcpSocket(this);
        pTcpSocket->connectToHost(IP, port);
        connect(pTcpSocket, SIGNAL(connected()), SLOT(slotConnected()));
        connect(pTcpSocket, SIGNAL(disconnected()), SLOT(slotDisconnected()));
        connect(pTcpSocket, SIGNAL(readyRead()), SLOT(slotReadyRead()));
        connect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
                this,         SLOT(slotError(QAbstractSocket::SocketError))
               );
    }
    else { // если соединения есть
        qDebug()<<"on_Button_Connect_clicked(): disconnecting...";
        pTcpSocket->disconnectFromHost();
    }
}

// Слот успешного соединения клиента с сервером:
void MyClient::slotConnected()
{
    qDebug()<<"slotConnected(): connected";
    Connect=true;
    ui->TEdit_RMsg->append("State: Connected");
    ui->LEdit_IPAdress->setEnabled(false);
    ui->LEdit_PortNumber->setEnabled(false);
    ui->Button_Connect->setText("Disconnect");
    ui->Button_Send->setEnabled(true);
}

// Слот отсоединения клиента с сервером:
void MyClient::slotDisconnected()
{
    qDebug()<<"slotDisconnected(): disconnected";
    Connect = false;
    ui->TEdit_RMsg->append("State: Disconnected");
    ui->LEdit_IPAdress->setEnabled(true);
    ui->LEdit_PortNumber->setEnabled(true);
    ui->Button_Connect->setText("Connect");
    ui->Button_Send->setEnabled(false);
}

// Слот приема данных от сервера:
void MyClient::slotReadyRead()
{
    qDebug()<<"slotReadyRead(): StartReceiveData";
    QString line = "";
    // Определяем размер входящего пакета:
    int bytesAvail = pTcpSocket->bytesAvailable();
    qDebug()<<"waitForInput(): Receive " << bytesAvail << "bytes";
    int cnt = 0;
    bool endOfStream = false;
    while (cnt < bytesAvail && (!endOfStream)) {
        char ch;
        int bytesRead = pTcpSocket->read(&ch, sizeof(ch));
        if (bytesRead == sizeof(ch)) {
            cnt++;
            line.append( ch );
        }
        else {
            endOfStream = true;
        }
    }
    ui->TEdit_RMsg->append("Receive: "+line);
    parsingRecMsg(line);

}

// Слот обработки ошибок в соединении клиента с сервером:
void MyClient::slotError(QAbstractSocket::SocketError err)
{
    qDebug()<<"slotError";
    QString strError =
        "Error: " + (err == QAbstractSocket::HostNotFoundError ?
                     "The host was not found." :
                     err == QAbstractSocket::RemoteHostClosedError ?
                     "The remote host is closed." :
                     err == QAbstractSocket::ConnectionRefusedError ?
                     "The connection was refused." :
                     QString(pTcpSocket->errorString())
                    );
    ui->TEdit_RMsg->append(strError);
}

// Обработчик нажатия кнопки Send:
void MyClient::on_Button_Send_clicked()
{
    qDebug()<<"on_Button_Send_clicked(): send...";
    QByteArray  arrBlock;
    arrBlock.append(QString(ui->LEdit_TMsg->text()));
    pTcpSocket->write(arrBlock);
    ui->TEdit_RMsg->append("Send: "+QString(arrBlock));
}

/*void MyClient::mouseMoveEvent(QMouseEvent* pe)
{
    QPoint bsc = myPicture->pos();
    int x = pe->x() - bsc.x();
    int y = pe->y() - bsc.y();
    if((x < 0)||(x > scene->width())||(y < 0)||(y > scene->height()))
    {
        mouseTracker->setText("out of scene");
        return;
    }
    mouseTracker->setText(QString::number(x) + "  " + QString::number(y));
}*/

// Метод для парсинга входящего сообщения:
void MyClient::parsingRecMsg(const QString &RecMsg){
    qDebug()<<"parsingRecMsg()";
    if (RecMsg.length()==22){
        int id = strtol(RecMsg.mid(0,2).toUtf8().data(),NULL,16);
        int x = strtol(RecMsg.mid(2,4).toUtf8().data(),NULL,16);
        int y = strtol(RecMsg.mid(6,4).toUtf8().data(),NULL,16);
        int z = strtol(RecMsg.mid(10,4).toUtf8().data(),NULL,16);
        int data1 = strtol(RecMsg.mid(14,2).toUtf8().data(),NULL,16);
        int data2 = strtol(RecMsg.mid(16,2).toUtf8().data(),NULL,16);
        int data3 = strtol(RecMsg.mid(18,2).toUtf8().data(),NULL,16);
        int state = strtol(RecMsg.mid(20,2).toUtf8().data(),NULL,16);
        QString state_s;
        if(state == 1) state_s = "work_ON";
        else state_s = "work_OFF";
        QVariantList data;
        data.append(id);
        data.append(x);
        data.append(y);
        data.append(z);
        data.append(data1);
        data.append(data2);
        data.append(data3);
        data.append(state_s);
        QSqlQuery query;
        query.prepare("SELECT * FROM TableSystNode WHERE NodeID=:NodeID");
        query.bindValue(":NodeID", id);
        query.exec();
        if(query.next()==false){
            // Вставляем данные в БД
            db->inserIntoTable(data);
            model->select();
            emit signalRepaint();
        }
        else{
            // Изменяем данные в БД
            db->updateTable(data);
            model->select();
            emit signalRepaint();
        }
    }
    else{
        qDebug()<<"parsingRecMsg(): bad RecMsg: "<<RecMsg;
    }

}

// Метод для инициализации модели представления таблицы БД:
void MyClient::setupModel(const QString &tableName, const QStringList &headers)
{
    /* Производим инициализацию модели представления данных
     * с установкой имени таблицы в базе данных, по которому
     * будет производится обращение в таблице
     * */
    model = new QSqlTableModel(this);
    model->setTable(tableName);
    // Устанавливаем названия колонок в таблице с сортировкой данных
    for(int i = 0, j = 0; i < model->columnCount(); i++, j++){
        model->setHeaderData(i,Qt::Horizontal,headers[j]);

    }
    // Устанавливаем сортировку по возрастанию данных по нулевой колонке
    model->setSort(0,Qt::AscendingOrder);

}

// Метод для отрисовки модели представления таблицы БД:
void MyClient::createModel()
{
    ui->tableView->setModel(model);             // Устанавливаем модель на TableView
    //ui->tableView->setColumnHidden(0, true);    // Скрываем колонку с id записей
    ui->tableView->verticalHeader()->hide();

    // Разрешаем выделение строк
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    // Устанавливаем режим выделения лишь одно строки в таблице
    ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
    // Устанавливаем размер колонок по содержимому
    ui->tableView->resizeColumnsToContents();
    ui->tableView->setColumnWidth(1,50);
    ui->tableView->setColumnWidth(2,50);
    ui->tableView->setColumnWidth(3,50);
    ui->tableView->setColumnWidth(4,50);
    ui->tableView->setColumnWidth(5,50);
    ui->tableView->setColumnWidth(6,50);
    ui->tableView->setUpdatesEnabled(true);
    ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);

    ui->tableView->horizontalHeader()->setStretchLastSection(true);
    model->select(); // Делаем выборку данных из таблицы
}

// Слот для выделения строки в таблице БД:
void MyClient::slotSelectRow(int idRow)
{
    // Выделяем нужную строку
    ui->tableView->selectRow(idRow);
    // Имитируем нажатие кнопки Tab, чтобы выделить строку
    QKeyEvent* pe = new QKeyEvent(QEvent::KeyPress,
            Qt::Key_Tab,Qt::NoModifier, "Tab");
    QApplication::sendEvent(this, pe);
}


void MyClient::on_Button_AddNode_clicked()
{
    pBar = new QProgressBar();
    pBar->setRange(0,0);
    pBar->setTextVisible(true);
    pBar->setFormat("Loading...");
    pBar->setAlignment(Qt::AlignCenter);
    pBar->show();
}


mygraphicview.h
#ifndef MYGRAPHICVIEW_H
#define MYGRAPHICVIEW_H

#include <QWidget>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QWheelEvent>
#include <qmath.h>
#include <math.h>
#include <QDebug>
#include <QRect>
#include <QScrollBar>
#include <QApplication>
#include <mypoint.h>
#include <QMessageBox>
#include <QtSql>
#include <database.h>
#include <QObject>

class MyGraphicView : public QGraphicsView
{
    Q_OBJECT
public:
    explicit MyGraphicView(QWidget *parent = 0);
       ~MyGraphicView();
    double CurZoom=1.0;
    bool FirstStart = true;

private:
    QGraphicsScene      *scene;     // Объявляем сцену для отрисовки
    QGraphicsItemGroup  *group_1;   // Объявляем первую группу элементов
    QGraphicsItemGroup  *group_2;   // Объявляем вторую группу элементов
    MyPoint *point;                 // Объявляем переменную для создания объектов на сцене
    DataBase *db;                   // Объявляем переменную для доступа к БД
    double minX = -250.0;              // Минимальное значение по оси Х
    double maxX = 250.0;            // Максимальное значение по оси Х
    int numXTicks = 10;             // Количество рисок по оси Х
    double minY = -250.0;              // Минимальное значение по оси Y
    double maxY = 250;              // Максимальное значение по оси Y
    int numYTicks = 10;             // Количество рисок по оси Y
    double spanX() const { return fabs(maxX - minX); }  // Разница по между макс и мин X
    double spanY() const { return fabs(maxY - minY); }  // Разница по между макс и мин Y
    double currentX;                // Текущее значение Х
    double currentY;                // Текущее значение Y
    bool StartDraw = false;         // Переменная для разрешения перерисовки сцены
    double pXmin;                   // Временная переменная для хранение мин значения оси Х
    double pYmax;                   // Временная переменная для хранение мин значения оси Y
    void clearScene();              // Метод для удаления всех элементов со сцены
    void adjustAxis(double &min, double &max, int &numTicks);// Метод для выбора оптимальных значений осей и рисок сцены

protected:
    void wheelEvent(QWheelEvent* event);
    void mouseMoveEvent(QMouseEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);

private slots:
    void slotFromPoint(int numberPoint, int pX, int pY);       // Слот для обработки сигнала из точки

public slots:
    void slotAlarmTimer();      // Cлот для обработчика переполнения таймера (в нем происходит рисование сцены)
    //void slotSelectedItem();

signals:
    void signalSelectRow(int numRow);
};

#endif // MYGRAPHICVIEW_H

mygraphicview.cpp
#include "mygraphicview.h"

MyGraphicView::MyGraphicView(QWidget *parent)
    : QGraphicsView(parent)
{
    qDebug()<<"MyGraphicView(): start";
    // Настраиваем отображение виджета и его содержимого:
    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);             // Отключим скроллбар по горизонтали
    this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);               // Отключим скроллбар по вертикали
    this->setAlignment(Qt::AlignCenter);                                    // Делаем привязку содержимого к центру
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);    // Растягиваем содержимое по виджету
    this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);         // В качестве якоря используется точка под курсором мышки.
    this->setRenderHint(QPainter::Antialiasing);                            // Устанавливаем сглаживание
    //this->setFocusPolicy(Qt::StrongFocus);
    scene = new QGraphicsScene();                                           // Инициализируем сцену для отрисовки
    scene->setItemIndexMethod(QGraphicsScene::NoIndex);                     // Линейный поиск элементов
    this->setScene(scene);                                                  // Устанавливаем сцену в виджет
    slotAlarmTimer();


    //timer = new QTimer();                   // Инициализируем Таймер
    // Подключаем СЛОТ для отрисовки к таймеру
    //connect(timer, SIGNAL(timeout()), this, SLOT(slotAlarmTimer()));
    //timer->start(50);                   // Стартуем таймер на 50 миллисекунд
    FirstStart = false;
}

MyGraphicView::~MyGraphicView()
{

}

// Метод отвечающий за перерисовку сцены
void MyGraphicView::slotAlarmTimer()
{
    // Запрещаем перерисование сцены
    StartDraw = true;
    qDebug()<<"slotAlarmTimer(): start";
    /* Удаляем все элементы со сцены,
     * если они есть перед новой отрисовкой
     * */
    clearScene();
    /* Устанавливаем размер сцены по размеру виджета
     * Первая координата - это левый верхний угол,
     * а Вторая - это правый нижний угол
     * */
    scene->setSceneRect(-250,-250,500,500);
    // Создаем кисти для рисования на сцене
    QPen penGreen(Qt::green);       // Задаём чёрную кисть
    QPen penRed(Qt::red);           // Задаём красную кисть
    QPen penGray(Qt::lightGray);         // Задаем серую кисть
    QPen penDarkGray(Qt::green); // Задаем темно-серую кисть
    penGray.setCosmetic(true);
    penDarkGray.setCosmetic(true);
    // Получаем текущее значение минимальных значений осей координат
    QPolygon pView = mapFromScene(QRect(0, 0, this->viewport()->width(), this->viewport()->height()));
    if (CurZoom < 2.0) {
        pXmin = 0;
        pYmax = 0;
    }
    else
    {
        pXmin = -pView.at(0).x()/CurZoom;
        pYmax = 500 / CurZoom + minY;
    }

    // Рисуем координатную ось Х:
    QRect rect(minX,minY,spanX(),spanY());
    for (int i = 0; i <= numXTicks; ++i) {
        int x = rect.left() + (i * (rect.width() - 1)/numXTicks);
        double label = minX + (i * spanX()/numXTicks);
        if (label == 0) scene->addLine(x+1,rect.top(),x+1,rect.bottom(),penDarkGray);
        else scene->addLine(x+1,rect.top(),x+1,rect.bottom(),penGray);
        //qDebug()<<"add line X:"<<x<<" "<<rect.top()<<" "<<x<< " "<< rect.bottom();
        QGraphicsSimpleTextItem *name = NULL;
        name = scene->addSimpleText(QString::number(label));
        name->setBrush(Qt::gray);
        name->setScale(1/CurZoom);
        int kname = spanX()/numXTicks;
        name->setPos(minX+i*kname+3/CurZoom, pYmax-14/CurZoom);
    }
    // Рисуем координатную ось Y:
    for (int j = 0; j <= numYTicks; ++j) {
        int y = rect.bottom() - (j * (rect.height() - 1)/numYTicks);
        double label = -(minY + (j * spanY()/numYTicks));
        if ((unsigned int)label == 0)
        {
            scene->addLine(rect.left(), y, rect.right(), y,penDarkGray);
            //qDebug()<<"LABEL:"<<label;
        } else scene->addLine(rect.left(), y, rect.right(), y,penGray);
        //qDebug()<<"add line Y:"<<rect.left()<<" "<<y<<" "<<rect.right()<< " "<< y;
        QGraphicsSimpleTextItem *name = NULL;
        name = scene->addSimpleText(QString::number(label));
        name->setBrush(Qt::gray);
        int kname = spanY()/numYTicks;
        name->setPos(pXmin+3/CurZoom, minY+j*kname-0.7*CurZoom);
        name->setScale(1/CurZoom);
    }
    scene->addRect(rect,penGray);

    // Рисуем местоположение абонентов системы:
    QSqlQuery query;
    db->selectTable(query);
    while (query.next()) {
         int numberP = query.value(0).toInt();
         int pX = query.value(1).toInt();
         int pY = query.value(2).toInt();
         qDebug()<<"slotAlarmTimer(): new point with cord X = "<<pX<<" Y = "<<pY;
         point = new MyPoint(pX,-pY,5.0,5.0,Qt::green,numberP);
         scene->addItem(point);
         point->setPos(pX,-pY);
         // Подключаем сигнал из точки к СЛОТу в главном классе
         connect(point,&MyPoint::signal1, this, &MyGraphicView::slotFromPoint);

    }
    // Разрешаем перерисование сцены
    StartDraw = false; 
}

/* // Методом перехватываем событие изменения размера виджет
void MyGraphicView::resizeEvent(QResizeEvent *event)
{
    timer->start(50);   // Как только событие произошло стартуем таймер для отрисовки
    QGraphicsView::resizeEvent(event);  // Запускаем событие родителького класса
}
*/

// Метод для удаления всех элементов со сцены:
void MyGraphicView::clearScene()
{
    // Перебираем все элементы сцены и удаляем их
    QList<QGraphicsItem*> all = items();
    for (int i = 0; i < all.size(); i++)
    {
        QGraphicsItem *gi = all[i];
        if(gi->parentItem()==NULL) {
            delete gi;
        }
    }
}

// Метод вращения колесика мыши:
void MyGraphicView::wheelEvent(QWheelEvent *event)
{
    // Scale the view / do the zoom
    const double scaleFactor = 1.15;
    if(event->delta() > 0)
    {
        // Zoom in
        if(CurZoom < 6.0){
            CurZoom = CurZoom*scaleFactor;
            qDebug()<<"wheelEvent(): CurZoom = " << CurZoom;
            scale(scaleFactor, scaleFactor);
            centerOn(mapToScene(event->pos()));
            QPolygon pView = mapFromScene(QRect(0, 0, this->viewport()->width(), this->viewport()->height()));
            qDebug()<<pView;
            minX = -pView.at(0).x()/CurZoom;
            maxX = 500 / CurZoom + minX;
            minY = -pView.at(0).y()/CurZoom;
            maxY = 500 / CurZoom + minY;
            adjustAxis(minX, maxX, numXTicks);
            adjustAxis(minY, maxY, numYTicks);
            qDebug()<<"numXTicks = "<<numXTicks;
            qDebug()<<"numYTicks = "<<numYTicks;
            qDebug()<<"minX = "<< minX << "; minY = " << minY;
            qDebug()<<"maxX = "<< maxX << "; maxY = " << maxY;
            slotAlarmTimer();
        } else qDebug()<<"wheelEvent(): posX = "<<event->pos().x()/CurZoom<< "posY = "<<event->pos().y()/CurZoom;
    }
    else
    {
        // Zooming out
        if (CurZoom > 1.10) {
            CurZoom = CurZoom/scaleFactor;
            qDebug()<<"wheelEvent(): CurZoom = " << CurZoom;
            scale(1.0 / scaleFactor, 1.0 / scaleFactor);
            centerOn(mapToScene(event->pos()));
            QPolygon pView = mapFromScene(QRect(0, 0, this->viewport()->width(), this->viewport()->height()));
            qDebug()<<pView;
            minX = -pView.at(0).x()/CurZoom;
            maxX = 500 / CurZoom + minX;
            minY = -pView.at(0).y()/CurZoom;
            maxY = 500 / CurZoom + minY;
            adjustAxis(minX, maxX, numXTicks);
            adjustAxis(minY, maxY, numYTicks);
            qDebug()<<"numXTicks = "<<numXTicks;
            qDebug()<<"numYTicks = "<<numYTicks;
            qDebug()<<"minX = "<< minX << "; minY = " << minY;
            qDebug()<<"maxX = "<< maxX << "; maxY = " << maxY;
            slotAlarmTimer();
        } else {
            minX = -250;
            maxX = 250;
            minY = -250;
            maxY = 250;
            numXTicks = 10;
            numYTicks = 10;
            qDebug()<<"wheelEvent(): posX = "<<event->pos().x()/CurZoom<< "posY = "<<event->pos().y()/CurZoom;
            slotAlarmTimer();
        }
    }
}

// Метод для определения оптимыльных значений рисок координатных осей:
void MyGraphicView::adjustAxis(double &min, double &max, int &numTicks)
{
    const int MinTicks = 5;
    double grossStep = (max - min) / MinTicks;
    double step = pow(10, floor(log10(grossStep)));
    qDebug()<<"Step = "<<step;
    if (5 * step < grossStep) step *= 5;
    else if (4 * step < grossStep) step *= 4;
    else if (3 * step < grossStep) step *= 3;
    else if (2 * step < grossStep) step *= 2;
    numTicks = (int)(ceil(max / step) - floor(min / step));
    if(CurZoom<1.10) numTicks = 10;
    if (CurZoom > 6.0) numTicks = 10;
    min = floor(min / step) * step;
    max = ceil(max / step) * step;
}

// Метод нажатия кнопки мыши:
void MyGraphicView::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::RightButton){
        QApplication::setOverrideCursor(QCursor(Qt::ClosedHandCursor));
        //this->viewport()->setCursor(Qt::ClosedHandCursor);
        // Store original position.
        currentX = event->x();
        currentY = event->y();
        //event->accept();
        qDebug()<<"mousePressEvent(): originX = "<<currentX<<"; originY = "<<currentY;
        return;
    }
    if (event->button() == Qt::LeftButton){
        slotAlarmTimer();
    }
    //event->ignore();
}

// Метод перемещения указателя мыши:
void MyGraphicView::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::RightButton) {
        this->horizontalScrollBar()->setValue(horizontalScrollBar()->value() - (event->x() - currentX));
        this->verticalScrollBar()->setValue(verticalScrollBar()->value() - (event->y() - currentY));
        currentX = event->x();
        currentY = event->y();
        qDebug()<<"mouseMoveEvent(): originX = "<<currentX<<"; originY = "<<currentY;
        event->accept();
        if(StartDraw == false && CurZoom != 1.0){
            QPolygon pView = mapFromScene(QRect(0, 0, this->viewport()->width(), this->viewport()->height()));
            qDebug()<<pView;
            minX = -pView.at(0).x()/CurZoom;
            maxX = 500 / CurZoom + minX;
            minY = -pView.at(0).y()/CurZoom;
            maxY = 500 / CurZoom + minY;
            qDebug()<<"minX = "<< minX << "; minY = " << minY;
            qDebug()<<"maxX = "<< maxX << "; maxY = " << maxY;
            adjustAxis(minX, maxX, numXTicks);
            adjustAxis(minY, maxY, numYTicks);
            qDebug()<<"numXTicks = "<<numXTicks;
            qDebug()<<"numYTicks = "<<numYTicks;
            qDebug()<<"minX = "<< minX << "; minY = " << minY;
            qDebug()<<"maxX = "<< maxX << "; maxY = " << maxY;
            slotAlarmTimer();
        }
        return;
    }
    event->ignore();
}

// Метод отпускания кнопки мыши:
void MyGraphicView::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button()==Qt::RightButton)
    {
        qDebug()<<"mouseReleaseEvent(): RightButton was released";
        QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
        event->accept();
        if(StartDraw == false && CurZoom != 1.0){
            QPolygon pView = mapFromScene(QRect(0, 0, this->viewport()->width(), this->viewport()->height()));
            qDebug()<<pView;
            minX = -pView.at(0).x()/CurZoom;
            maxX = 500 / CurZoom + minX;
            minY = -pView.at(0).y()/CurZoom;
            maxY = 500 / CurZoom + minY;
            adjustAxis(minX, maxX, numXTicks);
            adjustAxis(minY, maxY, numYTicks);
            qDebug()<<"numXTicks = "<<numXTicks;
            qDebug()<<"numYTicks = "<<numYTicks;
            qDebug()<<"minX = "<< minX << "; minY = " << minY;
            qDebug()<<"maxX = "<< maxX << "; maxY = " << maxY;
            slotAlarmTimer();
        }
    }
    event->ignore();
}

void MyGraphicView::slotFromPoint(int numberPoint, int pX, int pY)
{
    qDebug()<<"slotFromPoint(): click "<<numberPoint<<" node";
    QList<QGraphicsItem *> itemsSelected = scene->items(QPolygonF()
                                                        << QPointF(pX, pY)
                                                        << QPointF(pX, pY)
                                                        << QPointF(pX, pY)
                                                        << QPointF(pX, pY));
    foreach (QGraphicsItem *item, itemsSelected) {
        if(item->pos().x()!=0 && item->pos().y()!=0)
        {
            qDebug()<<"Item = "<<item;
        }
    }

    emit signalSelectRow(numberPoint);
}

  • EVILEG
  • Статья
  • 3 февраля 2017 г. 22:55

QML - Урок 027. Добавляем QML в проект на QWidget

QQuickWidget, QML, C++, QWidget

При разработке приложения на Qt может случиться такая ситуация, когда потребуется в приложение, написанное на QWidgets внедрить функционал, написанный на QML. Для решения подобной задачи может использоваться класс QQuickWidget , который служит для рендеринга QML.

Напишем простейший hello world, который позволит отрисовать код, написанный на QML в виджете, который помещён в окно, основанное на QWidget. Чтобы оно выглядело следующим образом:

Реклама
  • BoostEX
  • 17 августа 2017 г. 16:45

C++ - Тест 001. Первая программа и типы данных

  • Результат - 73 баллов
  • Nordman
  • 15 августа 2017 г. 20:40

C++ - Тест 005. Структуры и Классы

  • Результат - 66 баллов

C++ - Тест 002. Константы

  • Результат - 33 баллов
Последние комментарии
  • EVILEG
  • 17 августа 2017 г. 18:33

Qt/C++ - Урок 069. Шифрование методом XOR

Не обратил внимания на это, Проверял с большим текстом.. По идее не должно.

Qt/C++ - Урок 069. Шифрование методом XOR

Шифрует/дешифрует текст от 8 символов, так и должно быть?

  • EVILEG
  • 15 августа 2017 г. 20:32

Qt/C++ - Урок 048. QThread - работа с потоками с помощью moveToThread

Нууу... тут уже вопрос к самому Qt4.8. Если честно, идей нет, да и копаться в deprecated коде желания тоже нет.

  • t000r
  • 15 августа 2017 г. 19:49

Qt/C++ - Урок 048. QThread - работа с потоками с помощью moveToThread

В qt5.6 всё нормально заработало. С 4.8 - нет

  • EVILEG
  • 15 августа 2017 г. 17:44

Qt/C++ - Урок 050. Логирование событий Qt приложения в текстовый файл

Я полистал информацию в интернетах, вроде как кто-то пытается подружить его с Qt5, но успешных результатов не нашёл. Да и на сайте как-то не заметно информации о том, что конкретно ему нужно, ...

Сейчас обсуждают на форуме

Сборка Qt / C++ проекта под windows и linux

вы имели ввиду это? если да, то как то не работает((( #include <iostream>#include <bitset> // заголовочный файл битовых полей#include <iomanip> // для манип...

  • alex_lip
  • 17 августа 2017 г. 19:11

Я только учусь..(как правильно присвоить значение объекту другого класса)

А что вы думаете про директиву friend ? class A { friend void B::changeValue(); private: int _value;};class B { void changeValue() { a-&...

  • EVILEG
  • 16 августа 2017 г. 13:38

Перевод кодировки строки из windows 1251 в Utf-8

Здесь необходимо использовать QTextCodec. Вещь это очень хитрая в том плане, что объект этого класса необходимо создавать с определённой кодировкой. Поскольку он будет гонять данные от заданной код...

  • EVILEG
  • 15 августа 2017 г. 17:09

Переключение между Qt::WindowMaximized и Qt::WindowNoState при фиксированном размере окна.

Согласен - это велосипед, но это гораздо меньше, чем отключить оформление окна и написать своё оформление )) Например, как здесь .

  • EVILEG
  • 13 августа 2017 г. 13:51

SQLITE speed up

Заполняете в цикле из объекта query? Можете показать тот кусок кода, где выполняете эти манипуляции? Ускорить код разве только некоторым манипуляциями с указателями или ссылками, н...