Russian Qt Forum
Ноябрь 23, 2024, 08:38 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Обработка события мыши для нескольких виджетов  (Прочитано 11949 раз)
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();
}
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #1 : Май 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()), они позволяют перехватить события одного объекта в другом, при этом ты сам будешь решать передавать его в конечный объект или нет.
« Последнее редактирование: Май 28, 2010, 12:38 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
Einior
Гость
« Ответ #2 : Май 28, 2010, 12:40 »


Вот окно работающего приложения.
При нажатии на одну из клеток синих квадратов (класс SeaMap) в строке ввода должен появляться текст (для теста - это "qqq"). Однако этого не происходит.
Соединение сигнал-слот работает, проверено. Поэтому грешу именно на обработку событий.
В этом, собственно говоря, и проблема.

По коду: класс SeaMap - синие квадраты. HumanClient - основной класс, который и содержит остальные объекты.

Да, маусЭвент у класса SeaMap перегружен. Фильтры событий читал, но что-то не особо понял.
« Последнее редактирование: Май 28, 2010, 12:41 от Einior » Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #3 : Май 28, 2010, 12:44 »

клетки квадратов отдельные виджеты?
Да, маусЭвент у класса SeaMap перегружен.
маусЭвент или mousePressEvent? Всё должно работать, задачка простая же...
« Последнее редактирование: Май 28, 2010, 12:46 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
Einior
Гость
« Ответ #4 : Май 28, 2010, 12:47 »

Цитировать
клетки квадратов отдельные виджеты?
Нет. Каждый квадрат - отдельный виджет. Клетки нарисованы в событии рисования.
Цитировать
маусЭвент или mousePressEvent?
Точно Улыбающийся
Был mouseEvent, переопределил mousePressEvent - заработало.
Спасибо.
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #5 : Май 28, 2010, 12:50 »

Если чувствуешь что совсем мало знаний по Qt, почитай для начала Шлее "Qt 4.5", на многие будущие вопросы получишь ответы.
Записан

kubuntu/Win7/x64/NetBeans
Einior
Гость
« Ответ #6 : Май 30, 2010, 21:13 »

Не хотелось создавать отдельную тему, поэтому ещё один вопрос задам здесь.

Для QLineEdit задаётся валидатор в виде регулярного выражения. Регэксп должен обозначать выражение, которое первым символом имеет буквы из интервала A-J, затем цифры 1-9, и если перед этим шла единица, то возможен 0 (т.е. возможен ввод чисел 1-10). Например, выражения A5, C10.
С первой частью выражения проблем нет - [A-J][1-9], а вот как добавить ноль, не знаю.
Подскажите, пожалуйста.

Заранее благодарю за помощь.
Записан
Anarion
Гость
« Ответ #7 : Май 30, 2010, 22:49 »

Например:

Код:
QRegExp rx("[A-J]([1-9]|[1][0])");
QRegExpValidator *rxv = new QRegExpValidator(rx,this);
ui->lineEdit->setValidator(rxv);
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.068 секунд. Запросов: 22.