Название: Обработка события мыши для нескольких виджетов
Отправлено: Einior от Мая 28, 2010, 10:49
Ситуация такая. Создан класс-наследник от QWidget, который представляет собой главное окно программы. 2 поля в нём - объекты ещё одного класса, унаследованного от QWidget. Во втором классе определен обработчик событий мыши, который при некотором событии (нажатие левой кнопки) должен посылать сигнал некоторому слоту родительского объекта. Так вот, при нажатии кнопки событие не обрабатывается. В интернете видел информацию, что событие мыши в кьюте перехватываются активным окном (в моём случае, объект первого класса). Каким образом это можно обойти? Т.е. сделать так, чтобы событие обрабатывалось, извиняюсь за тавталогию, обработчиком второго класса? Код: #include <QApplication> #include "humanclient.h"
int main(int argc, char **argv) { QApplication app(argc, argv); HumanClient client("localhost", 1516);
client.show(); return app.exec(); } ------------------------------------------------ #ifndef HUMANCLIENT_H #define HUMANCLIENT_H
#include <QWidget> #include <QTcpSocket> #include "seamap.h"
class QTextEdit; class QLineEdit;
class HumanClient : public QWidget { Q_OBJECT private: QTcpSocket *tcpSocket; QTextEdit *textInfo; QLineEdit *textInput; quint16 nextBlockSize; SeaMap *firstMap; SeaMap *secondMap;
public: HumanClient(const QString& host, int port, QWidget *parent = 0);
signals:
public slots: void slotReadyRead(); void slotError(QAbstractSocket::SocketError); void slotSendToCerver(); void slotConnected(); };
#endif // HUMANCLIENT_H ---------------------------------------------- #include <QtGui> #include <QtCore> #include <QtNetwork> #include "humanclient.h"
HumanClient::HumanClient(const QString& host, int port, QWidget *parent) : QWidget(parent), nextBlockSize(0)
{ tcpSocket = new QTcpSocket(this); tcpSocket->connectToHost(host, port);
connect(tcpSocket, SIGNAL(connected()), SLOT(slotConnected())); connect(tcpSocket, SIGNAL(readyRead()), SLOT(slotReadyRead())); connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotError(QAbstractSocket::SocketError)));
textInfo = new QTextEdit; textInput = new QLineEdit;
textInfo->setReadOnly(true); // QRegExp regExp("[A-J][0-9]"); // textInput->setValidator(new QRegExpValidator(regExp, this));
firstMap = new SeaMap(this); secondMap = new SeaMap(this);
QPushButton *sendButton = new QPushButton("Send");
connect(sendButton, SIGNAL(clicked()), SLOT(slotSendToCerver())); connect(textInput, SIGNAL(returnPressed()), this, SLOT(slotSendToCerver())); connect(firstMap, SIGNAL(seaCoord(const QString&)), textInput, SLOT(setText(const QString&))); connect(secondMap, SIGNAL(seaCoord(const QString&)), textInput, SLOT(setText(const QString&)));
QVBoxLayout *vBoxLayout = new QVBoxLayout; vBoxLayout->addWidget(new QLabel("<H1>Client</H1>")); vBoxLayout->addWidget(textInfo); vBoxLayout->addWidget(textInput); vBoxLayout->addWidget(sendButton);
QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addWidget(firstMap); mainLayout->addWidget(secondMap); mainLayout->addLayout(vBoxLayout);
setLayout(mainLayout); }
void HumanClient::slotReadyRead() { QDataStream input(tcpSocket); QString str;
for (;;) { if (!nextBlockSize) { if (tcpSocket->bytesAvailable() < sizeof(quint16)) break; input >> nextBlockSize; }
if (tcpSocket->bytesAvailable() < nextBlockSize) break; input >> str;
textInfo->append(str); nextBlockSize = 0; } }
void HumanClient::slotError(QAbstractSocket::SocketError error) { QString strError;
strError = "Error: " + (error == QAbstractSocket::HostNotFoundError ? "The host not found." : error == QAbstractSocket::RemoteHostClosedError ? "The remote host is closed." : error == QAbstractSocket::ConnectionRefusedError ? "The connection was refused." : QString(tcpSocket->errorString())); textInfo->append(strError); }
void HumanClient::slotSendToCerver() { QByteArray block; QDataStream output(&block, QIODevice::WriteOnly);
output << quint16(0) << textInput->text(); output.device()->seek(0); output << quint16(block.size() - sizeof(quint16));
tcpSocket->write(block); textInput->setText(""); }
void HumanClient::slotConnected() { textInfo->append("Recieved the connected() signal"); } ------------------------------------------------ #ifndef SEAMAP_H #define SEAMAP_H
#include <QWidget>
class SeaMap : public QWidget { Q_OBJECT
private: quint8 **map;
protected: void paintEvent (QPaintEvent *event); void mouseEvent (QMouseEvent *event);
public: SeaMap(QWidget *parent = 0); ~SeaMap();
signals: void seaCoord(const QString& str); };
#endif // SEAMAP_H -------------------------------------- #include "seamap.h" #include "qpainter.h" #include <QtGui/qevent.h>
SeaMap::SeaMap(QWidget *parent) : QWidget(parent) { int i, j;
map = new quint8*[10]; for (i = 0; i < 10; i++) { map[i] = new quint8[10]; for (j = 0; j < 10; j++) map[i][j] = 0; } setFixedSize(150, 150);
}
SeaMap::~SeaMap() { for (int i = 0; i < 10; i++) delete []map[i];
delete []map; }
void SeaMap::paintEvent (QPaintEvent* event) { QPainter paint(this); QBrush seaBrush = Qt::blue; QBrush brush = Qt::black; int i, j;
for (i = 0; i < 10; i++) for (j = 0; j < 10; j++) if (!map[i][j]) { paint.setBrush(seaBrush); paint.drawRect(i * 15, j * 15, 15, 15); } else { paint.setBrush(brush); paint.drawRect(i * 15, j * 15, 15, 15); }
} //не работает, т.к. нажатие мыши на главном объекте void SeaMap::mouseEvent (QMouseEvent *event) { int x = event->pos().x() / 15; int y = event->pos().y() / 15;
if (event->button() == Qt::LeftButton) { //QChar ch(x + 65); QString str = "qqq"; emit seaCoord(str); } update(); }
Название: Re: Обработка события мыши для нескольких виджетов
Отправлено: serg_hd от Мая 28, 2010, 12:31
Нужно у второго класса перегрузить соответствующий метод. И вообще, как проверяешь нажатие правой кнопки? У события QMouseEvent есть методы button() и buttons(). Например, второй возвращает битовую комбинацию из некоторых значений (в зависимости от того, какая кнопка нажата) и поэтому воспользоваться им можно напр. так: C++ (Qt) void MouseObserver::mousePressEvent(QMouseEvent* event) { if (event->buttons() & Qt::RightButton) { //нажата правая } }
А вообще все события приложения сначала направляются в QApplication (или QCoreApplication). Далее все объекты событий поступают в метод event(), который дальше вызывает более специализированный метод данного объекта. Так что можешь его также переписать по своему усмотрению. И как бы не совсем понял в чём конкретно пролема. Посмотри ещё на всякий случай в сторону фильтров событий (для реализации фильтра надо унаследовать QObject и переопределить метод eventFilter(), а устанавливать фильтр через installEventFilter()), они позволяют перехватить события одного объекта в другом, при этом ты сам будешь решать передавать его в конечный объект или нет.
Название: Re: Обработка события мыши для нескольких виджетов
Отправлено: Einior от Мая 28, 2010, 12:40
(http://i036.radikal.ru/1005/0f/15e9773c30b6.png) Вот окно работающего приложения. При нажатии на одну из клеток синих квадратов (класс SeaMap) в строке ввода должен появляться текст (для теста - это "qqq"). Однако этого не происходит. Соединение сигнал-слот работает, проверено. Поэтому грешу именно на обработку событий. В этом, собственно говоря, и проблема.
По коду: класс SeaMap - синие квадраты. HumanClient - основной класс, который и содержит остальные объекты.
Да, маусЭвент у класса SeaMap перегружен. Фильтры событий читал, но что-то не особо понял.
Название: Re: Обработка события мыши для нескольких виджетов
Отправлено: serg_hd от Мая 28, 2010, 12:44
клетки квадратов отдельные виджеты? Да, маусЭвент у класса SeaMap перегружен.
маусЭвент или mousePressEvent? Всё должно работать, задачка простая же...
Название: Re: Обработка события мыши для нескольких виджетов
Отправлено: Einior от Мая 28, 2010, 12:47
клетки квадратов отдельные виджеты? Нет. Каждый квадрат - отдельный виджет. Клетки нарисованы в событии рисования. маусЭвент или mousePressEvent? Точно :) Был mouseEvent, переопределил mousePressEvent - заработало. Спасибо.
Название: Re: Обработка события мыши для нескольких виджетов
Отправлено: serg_hd от Мая 28, 2010, 12:50
Если чувствуешь что совсем мало знаний по Qt, почитай для начала Шлее "Qt 4.5", на многие будущие вопросы получишь ответы.
Название: Re: Обработка события мыши для нескольких виджетов
Отправлено: Einior от Мая 30, 2010, 21:13
Не хотелось создавать отдельную тему, поэтому ещё один вопрос задам здесь.
Для QLineEdit задаётся валидатор в виде регулярного выражения. Регэксп должен обозначать выражение, которое первым символом имеет буквы из интервала A-J, затем цифры 1-9, и если перед этим шла единица, то возможен 0 (т.е. возможен ввод чисел 1-10). Например, выражения A5, C10. С первой частью выражения проблем нет - [A-J][1-9], а вот как добавить ноль, не знаю. Подскажите, пожалуйста.
Заранее благодарю за помощь.
Название: Re: Обработка события мыши для нескольких виджетов
Отправлено: Anarion от Мая 30, 2010, 22:49
Например: QRegExp rx("[A-J]([1-9]|[1][0])"); QRegExpValidator *rxv = new QRegExpValidator(rx,this); ui->lineEdit->setValidator(rxv);
|