PDA

View Full Version : [problem] No mouse input to child widget



Demandred
12th April 2010, 15:24
Hello everybody,

First of all: I'm quite new to Qt and still learning. I'm using Qt Creator 1.2.1 with Qt 4.5.2.

My application is set up as follows:
I have a mainwindow, in which I load a "menu" widget this menu contains buttons at the bottom of the screen and a widget area (QWidget) as the upper part of the screen.

When one of the buttons on the bottom of the screen is pressed, another widget is shown/embedded in the widget area (which is called extWidget).
The embedded widget (StdConfig) is created in the menu constructor.



// Display widget in container
m_ui->extWidget = StdConfig;
StdConfig->show();


StdConfig contains 7 buttons in a grid layout. For testing I put a messagebox under one of the buttons.

The problem is this. My menu responds fine to my mouse input and the desired widget is displayed in the widget area.
Only when I move my mouse over the widget area, the buttons in the displayed widget are not responding.
The buttons don't light up when I move my mouse over them, and nothing happens when I click the buttons. No code gets executed and no animation of clicking is displayed.

I must be doing something wrong and it's probably very basic.
Can somebody help me and try to explain what I'm missing here?

Thank you for your time.
D


The parent of the StdConfig widget is my menu widget.

JD2000
12th April 2010, 18:35
There could be a number of things going on here, how did you implement the StdConfig buttons?

In the UI designer if you right click on a button and goto slot -> clicked(), is this where your messagebox code is?

Any chance of seeing the source code?

Demandred
13th April 2010, 07:45
Hi JD2000. Thank you for the reply.

I did the clicked button implementation a bit different, I created a slot myself and inserted the code there. But your statement made me realize that I don't need this. So I changed the code according to your post. Unfortunately this does not fix the problem.

After that I made a small change to the code for testing and when the unitconfigStd widget runs in a seperate window (not in the widget container of "menu") the controls respond as expected.
I built it back again to the original container system so you can see what I'm doing. I posted all the used code below. Except for the mainwindow which is nothing more then the default container for mainmenu.

Sorry if it's a bit much or chaotic. I just placed everything because I don't know what you might need to get an insight in the problem.
If you need any more information I'll try to provide it :)

This is the code I'm using now:

mainmenu.h


#ifndef MAINMENU_H
#define MAINMENU_H

#include <QtGui/QWidget>
#include "overlaymenu.h"
#include "unitconfigstd.h"

namespace Ui {
class MainMenu;
}

class MainMenu : public QWidget {
Q_OBJECT
public:
MainMenu(QWidget *parent = 0);
~MainMenu();
void SetOverlayMenu(QWidget *oMenu = 0);

protected:
void changeEvent(QEvent *e);

private:
Ui::MainMenu *m_ui;
QWidget * OverMenu;
unitconfigStd * StdConfig;

signals:
void MenuClicked();

public slots:
void DisplayWindow(int windowNr);
};

#endif // MAINMENU_H


mainmenu.cpp

In mainmenu.cpp an overlay menu is used which is a non-contained widget which displays itself on top of everything else when a button is pressed.
You can compare this to the Windows Start button. The overlay menu is positioned in the main function of the main.cpp file of the project.


#include "mainmenu.h"
#include "ui_mainmenu.h"

MainMenu::MainMenu(QWidget *parent) :
QWidget(parent),
m_ui(new Ui::MainMenu)
{
// Create the StdConfig window
StdConfig = new unitconfigStd(this);
// do not display it yet
StdConfig->hide();

m_ui->setupUi(this);

// Set the extWidget container item to zero as initialization
m_ui->extWidget = 0;
// connect the btMenu click to the publicaly available signal MenuClicked() so external items (the overlay menu in this case) can connect to it.
connect(m_ui->actionBtMenu,SIGNAL(triggered()), this, SIGNAL(MenuClicked()));
}

MainMenu::~MainMenu()
{
delete m_ui;
}

void MainMenu::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
m_ui->retranslateUi(this);
break;
default:
break;
}
}

// A link to the overlay menu.
void MainMenu::SetOverlayMenu(QWidget *oMenu){
OverMenu = oMenu;
}

// Display a window in the extWidget container according to the clicked menu button
void MainMenu::DisplayWindow(int windowNr) {
switch(windowNr) {
case 0: // no window to display
if (m_ui->extWidget != 0) {
m_ui->extWidget->hide();
}
break;

case 2: // button Unit Configuration (Standard) clicked
m_ui->extWidget = StdConfig;
StdConfig->show();
break;

default:
if (m_ui->extWidget != 0) {
m_ui->extWidget->hide();
}
break;
}
}


The overlay menu converts it's button clicks to a single signal with an integer value indicating which button was clicked.
(PS. I am aware there is some redundant code for the button-click handling. I will clean this up when everything works)

overlaymenu.h


#ifndef OVERLAYMENU_H
#define OVERLAYMENU_H

#include <QtGui/QWidget>

namespace Ui {
class OverlayMenu;
}

class OverlayMenu : public QWidget {
Q_OBJECT
public:
OverlayMenu(QWidget *parent = 0);
~OverlayMenu();

protected:
void changeEvent(QEvent *e);

private:
Ui::OverlayMenu *m_ui;

public slots:
// show or hide the overlay menu
void DisplayMenu();

// unused at this moment.
void SetButton1Caption(QString caption);
void SetButton2Caption(QString caption);
void SetButton3Caption(QString caption);
void SetButton4Caption(QString caption);
void SetButton5Caption(QString caption);

// Convert a button-click to a MenuButtonClicked signal with the corresponding integer value as parameter.
void Button1Clicked() { emit MenuButtonClicked(1); }
void Button2Clicked() { emit MenuButtonClicked(2); }
void Button3Clicked() { emit MenuButtonClicked(3); }
void Button4Clicked() { emit MenuButtonClicked(4); }
void Button5Clicked() { emit MenuButtonClicked(5); }
void Button6Clicked() { emit MenuButtonClicked(6); }

signals:
void MenuButton1Clicked();
void MenuButton2Clicked();
void MenuButton3Clicked();
void MenuButton4Clicked();
void MenuButton5Clicked();
void MenuButton6Clicked();
// This is currently the only signal that is realy used to send the clicked button as an integer.
void MenuButtonClicked(int);
};

#endif // OVERLAYMENU_H


overlaymenu.cpp


#include "overlaymenu.h"
#include "ui_overlaymenu.h"

OverlayMenu::OverlayMenu(QWidget *parent) :
QWidget(parent),
m_ui(new Ui::OverlayMenu)
{
m_ui->setupUi(this);

// Export all button clicks as public signals of the menu.
connect(m_ui->button1,SIGNAL(clicked()),this,SLOT(Button1Clicked ()));
connect(m_ui->button2,SIGNAL(clicked()),this,SLOT(Button2Clicked ()));
connect(m_ui->button3,SIGNAL(clicked()),this,SLOT(Button3Clicked ()));
connect(m_ui->button4,SIGNAL(clicked()),this,SLOT(Button4Clicked ()));
connect(m_ui->button5,SIGNAL(clicked()),this,SLOT(Button5Clicked ()));
}

OverlayMenu::~OverlayMenu()
{
delete m_ui;
}

void OverlayMenu::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
m_ui->retranslateUi(this);
break;
default:
break;
}
}

// SLOTS

void OverlayMenu::DisplayMenu()
{
if (this->isVisible())
{
this->hide();
}
else
{
this->show();
}
}

void OverlayMenu::SetButton1Caption(QString caption)
{
m_ui->button1->setText(caption);
}

void OverlayMenu::SetButton2Caption(QString caption)
{
m_ui->button2->setText(caption);
}

void OverlayMenu::SetButton3Caption(QString caption)
{
m_ui->button3->setText(caption);
}

void OverlayMenu::SetButton4Caption(QString caption)
{
m_ui->button4->setText(caption);
}

void OverlayMenu::SetButton5Caption(QString caption)
{
m_ui->button5->setText(caption);
}


And finally the unitconfigstd which contains only the code for the QMessageBox at this moment.

unitconfigstd.h


#ifndef UNITCONFIGSTD_H
#define UNITCONFIGSTD_H

#include <QtGui/QWidget>
#include <QMessageBox>

namespace Ui {
class unitconfigStd;
}

class unitconfigStd : public QWidget {
Q_OBJECT
public:
unitconfigStd(QWidget *parent = 0);
~unitconfigStd();

protected:
void changeEvent(QEvent *e);

private:
Ui::unitconfigStd *m_ui;

private slots:
void on_bt11_clicked();
};

#endif // UNITCONFIGSTD_H


and unitconfigstd.cpp


#include "unitconfigstd.h"
#include "ui_unitconfigstd.h"

unitconfigStd::unitconfigStd(QWidget *parent) :
QWidget(parent),
m_ui(new Ui::unitconfigStd)
{
m_ui->setupUi(this);
}

unitconfigStd::~unitconfigStd()
{
delete m_ui;
}

void unitconfigStd::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
m_ui->retranslateUi(this);
break;
default:
break;
}
}

// bt11 is the button on the 1st row and the 1st column of the grid (top-left corner).
void unitconfigStd::on_bt11_clicked()
{
QMessageBox msgBox;
msgBox.setText("A Test box!");
msgBox.exec();
}


Main.cpp links the buttonclick to display to overlay menu to the show/hide function of the overlaymenu.
and links the MenuButtonClick(int) to the DisplayWindow(int) to display the correct window when an overlay menu button is clicked.

main.cpp


#include <QtGui/QApplication>
#include "mainwindow.h"
#include "mainmenu.h"
#include "overlaymenu.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
MainMenu *menu = new MainMenu(&w);
OverlayMenu *oMenu = new OverlayMenu(&w);
int h,off;

// Show main window + main menu.
w.show();
menu->show();
// Hide the overlay menu for now.
oMenu->hide();

// Position the overlay menu according to the menu.
off = 80 + oMenu->height();
h = w.height() - off;
oMenu->move(0,h);

// Link the overlay menu to the menu
menu->SetOverlayMenu(oMenu);

// Link MenuButton_Clicked SIGNAL to DisplayMenu SLOT.
menu->connect(menu,SIGNAL(MenuClicked()),oMenu,SLOT(Disp layMenu()));
menu->connect(oMenu,SIGNAL(MenuButtonClicked(int)),menu, SLOT(DisplayWindow(int)));

// Set the menu as central widget of the mainWindow.
w.setCentralWidget(menu);
return a.exec();
}

Demandred
13th April 2010, 13:44
Okay, I've tried some other things, and I discovered that if I raise() the child widget that everything works as it should. So somehow the widget in the container is below a transparent widget (if it can be) and does not get any mouse input.

If anybody knows how to remove this effect I would be happy, but at least I have a work-around for now.