понедельник, 16 декабря 2013 г.

Qt. Как отследить перемещение мыши без нажатой кнопки

Qt. Как отследить перемещение мыши без нажатой кнопки?

Как отследить перемещения мыши на каком-бы то ни было виджете? Тут есть несколько вариантов:
  1. отслеживать событие.
  2. поставить фильтр.
  3. сделать захват мыши.
Сразу оговорюсь, пока вариант 3 мы рассматривать не будем (да и использовать его официальная документация не рекомендует).
Допустим, что отслеживать будем событие на форме.

Вариант 1.

Нам надо переопределить метод void mouseMoveEvent(QMouseEvent *). Поэтому просто в реализацию формы прописываем данный метод:

void MainWindow::mouseMoveEvent(QMouseEvent *me)
{
  qDebug() << tr("mouseEvent emitted: [x, y] = [%1, %2]"). 
              arg(me->x()).arg(me->y());
}

Но тут есть одно НО! Дело в том, что по умолчанию данное событие 
возникает только в случае нажатия одной из клавиш мыши. Чтобы можно 
было отследить движение мыши в "свободном полете", нам необходимо 
установить ее отслеживание с помощью метода 
 
void setMouseTracking(bool)
 
поэтому в конструкторе добавляем его:
 
this->setMouseTracking(true);
 
и такой же метод для виджета centralWidget() 
centralWidget()->setMouseTracking(true);
 
Получаем вот такой код:
 
#include "mainwindow.h"
#include "qmessagebox"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);

  this->setMouseTracking(true);
  centralWidget()->setMouseTracking(true);
}

MainWindow::~MainWindow()
{
  delete ui;
}

void MainWindow::mouseMoveEvent(QMouseEvent *me)
{
  qDebug() << tr("mouseEvent emitted: [x, y] = [%1, %2]")
               .arg(me->x()).arg(me->y());
}



Вариант 2:

а можно установить фильтр и тогда мы в одной функции сможем отслеживать сразу несколько событий. Делается это так:


#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);




  this->setMouseTracking(true);
  centralWidget()->setMouseTracking(true);

 
 this->installEventFilter(this);
}
 

bool MainWindow::eventFilter(QObject* obj, QEvent* event)
{
  if (event->type() == QEvent::MouseMove)
    {
      QMouseEvent* me = static_cast<QMouseEvent*>(event);
      if (me)
        qDebug() << tr("mouseEvent emitted: [x, y] = [%1, %2]")
                       .arg(me->x()).arg(me->y());
      else
        qDebug() << tr("Стремное событие: %1");
    }
  return QMainWindow::eventFilter(obj, event);
}
 


В обоих случаях есть второе НО! событие не будет обрабатываться, 
если курсор мыши находится над дочерним элементом. Поэтому если необходимо 
"сквозное" отслеживание, то данный фильтр надо ставить для каждого 
дочернего элемента.

Qt. предотвращение закрытия окна программы

Qt. предотвращение закрытия окна программы

Примечание: речь идет о Qt на виджетах.

Даже если у вас приложение состоит из одной формы, то в любом случае его можно закрыть кнопкой в заголовке или нажатием быстрых клавиш. Чтобы это предотвратить, надо всего навсего переопределить стандартное событие виджета closeEvent. Оно имеет следующее определение:

virtual void closeEvent(QCloseEvent *event);

таким образом, если мы имеем, например, форму MainWindow, то в заголовке (.h) пишем такой код:

class MainWindow : public QMainWindow
{
...
 virtual void closeEvent(QCloseEvent *event);
... 
};

 



а в файле реализации непосредственно сам метод:
 

void MainWindow::closeEvent(QCloseEvent* event)
{
  int quit = QMessageBox::information(this,  
                  "Realy quit?", "Are you sure?", tr("Yes"), tr("No"));
  quit == 0 ?  event->accept(): event->ignore();
}
 
и не забываем прописать все необходимые инклюды в начале страницы:
 
#include "qmessagebox"
#include "qcloseevent" 
 


Теперь любая попытка закрыть данное окно приведет к появлению 
вашего сообщения.


четверг, 12 декабря 2013 г.

Облегченное консольное приложение с дебагом

Облегченное консольное приложение с дебагом


#include <QDebug> // для вывода отладочной информации
#include <QTextStream>      // для потокового ввода/вывода

int main()
{
    QTextStream cin(stdin);     // связываем текстовый поток со 
                                // стандартным потоком ввода
    QTextStream cout(stdout);   // аналогично для стандартного потока  
                                // вывода

    cout.setCodec("CP866");     // для DOS зададим кодовую страницу

    int a = 0;
    cout << QString::fromUtf8("Введите значение: "), cout.flush();
    cin >> a;
    cout << QString::fromUtf8("Вы ввели a=") << a;

    qDebug() << "Введенное значение:" << a;
    
    return 0;
}
 
 
 
Вывод отладочной информации осуществляется с помощью статического? метода
qDebug. Всего подобных методов 4 с соответствующим характером действия:

  • qDebug()
  • qWarning()
  • qCritical()
  • qFatal()

отключить их можно с помощью директивы компилятора QT_NO_DEBUG_OUTPUT

Qt. Как вывести сообщение пользователю?

Как вывести сообщение пользователю?

для этого существует класс QMessageBox.

Использовать его можно так:

        QMessageBox msg;
    msg.setText(tr("Вы действительно хотите выйти?"));
    msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
    msg.setDefaultButton(QMessageBox::No);
    msg.setDetailedText(tr("Что вам тут сказать?<br>это<h1>HTML</h1>"));
        if (msg.exec() == QMessageBox::Yes)
        ...
 
Или через статические методы:
 
    int ret = QMessageBox::information(this,  
               "Статическое сообщение",  
               "Ну это сообщение, не видишь?", 
               QMessageBox::Ok | QMessageBox::Cancel | QMessageBox::Abort, 
               QMessageBox::Ok 
            ); 
 
из аналогичных статических методов доступны:
     information()
     question()
     warning()
     critical()  
с соответствующим предназначением.