PDA

View Full Version : Button in OpenGL



Atomic_Sheep
30th August 2012, 13:52
Hi guys, I'm trying to create buttons inside an OpenGL scene.

I have created a class for the OpenGL window and my program opens up and displays my picture in OpenGL. I have drawn buttons on the picture and now I'm trying to get mouse click inputs recognised. I'm just using Qt's mousePressEvent to detect mouse clicks inside the OpenGL window and am using signals and slots to emit the location of the mouse click in a QPoint object.

My other class is the Button class which I will use for other purposes (hence trying to do it this way rather then just having the whole implementation done in my OpenGL class).

So anyway, here's my button class:

button.cpp


#ifndef BUTTON_H
#define BUTTON_H

#include <QWidget>
#include <QMessageBox>
#include <QMouseEvent>

class Button : public QWidget
{
Q_OBJECT
public:
explicit Button(QWidget *parent = 0);

int m_iXLocation;
int m_iYLocation;
int m_iWidth;
int m_iHeight;

Button(int iXLocation, int iYLocation, int iWidth, int iHeight) : m_iXLocation(iXLocation), m_iYLocation(iYLocation), m_iWidth(iWidth), m_iHeight(iHeight)
{}

void SetButtonParameters(int iXLocation, int iYLocation, int iHeight, int iWidth);

//virtual void mousePressEvent(QMouseEvent *event);
void ButtonClickedCheck();

QPoint mousePosition;

signals:
public slots:
void LocationGrabber(QPoint Location);
};

#endif // BUTTON_H

So as you can see... the button class the parameters which set the button dimensions and location and the only thing that it receives as input from the OpenGL window is the location of the mouse click... I haven't figured out the transformation from OpenGL coordinates to window coordinates yet, but I'm aware of it and will do so in due course.

Anyway... where should I create the instances of the buttons? Inside the constructor of the OpenGL class? or inside the constructor of the class which houses the ui? I've put in in the latter, however for some reason the signals and slots aren't picking up the clicks form the OpenGL window and my debugging message boxes aren't popping up... well to quite frank, I can't even compile it as I'm the parameters I'm inputting into connect (in order to connect slots) aren't really working. I know this has a lot of Qt related stuff, but it's still more of an object oriented question and I hope you can look past my problems with the Qt components.

mainwindow.cpp


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

mainwindow::mainwindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::mainwindow)
{
Button Button1(0,0,50,50);
mainwindow::connect(mainwindowWidget, SIGNAL(MouseClickLocation(QPoint MousePositionAtClick)), Button1, SLOT(LocationGrabber(QPoint Location)));
ui->setupUi(this);
}

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

Maybe I made a mistake in the connect function? Maybe I need to use references somewhere? And yes, I've included button.h in the header for mainwindow.cpp

john_god
1st September 2012, 16:22
your Button1 gets out of scope has the constructor exit. Try declaring it as a pointer.

Atomic_Sheep
5th September 2012, 06:51
Hi John, thanks, got it to work. Another question. I would like to create different types of buttons e.g. one that does something i.e. a function, one that outputs a value such as a letter or something... for this, I've written different initialiser lists. However I'm not sure whether this is enough to differentiate between the buttons upon instantiation. i.e. when I instantiate a function button, I want it to do a callback or send out a signal (Qt) that will then be received somewhere else and do something... so in this case all I want to do is specify that this button is a function button. However if I want to create a button that spits out a letter, I want to be able to assign a letter to that button upon instantiation/initialisation. Since the button has many different member variables, if I create a particular instance of a button, what happens to the unused class member variables? Do they acquire the default constructor values... do they remain uninitialised? Not sure if I've explained myself clearly enough.

Also... another question... lets say I create an object, is it possible to somehow pass the actual name of the object without needing to implement an additional member variable inside the class and declaring the name of that object upon instantiation of that object?

john_god
7th September 2012, 05:17
Not sure if I understand your questions, but you can define diferent constructors to define diferent member initialization/function calls when instantiating. If you are coding lots of diferent buttons perhaps you should consider using derived class buttons, to get a cleaner code and cleaner logic. If you do that, for the name of the object, you can avoid member variable, using just one method, something like this:


class ButtonA : public Button
{
public:
ButtonA();
virtual QString name() const{return "buttonA";}
.........
}

You will not need to set the object name at construction time, and will be able to get it whenever you want it.

Atomic_Sheep
7th September 2012, 07:07
Ah yes good point, I actually started doing this this way a few months back when I started this problem and have since forgotten that I did it this way. I'll look into it again. My concern was simply the fact that some initialiser lists don't address various member variables or functions and that's what I was worried about since my understanding is that the default constructor isn't called if you call an overloaded one.

Atomic_Sheep
4th June 2014, 10:09
The method of using derived classes ended up being useful under a rather narrow set of circumstances. I'm trying to expand the functionality of my button class. Previously I created derived classes such as Button::AlphanumericButton and Button::NumericButton Button::Function which basically allowed me to assign a numerical or alphanumerical value to these, however I would like for my buttons to be able to do something not just store values. For Button::Function, I just kept adding a bunch of different function names under #define and then inside the classes that actually used the buttons I would basically create functions for each of the functionalities that I needed and used simple if statements:


void MyApp1::FunctionMultiply()
{
if(cButton.Function() == MULTIPLY) //sorry not a programmer, cButton.Function() might not be right, haven't written code in a while, but basically I'm invoking the member variable that stores the function value as per defines.
{
//do multiply
}
}


and then another app that I'm using would have:


void MyApp2::FunctionGetDatabaseValue()
{
if(cButton.Function() == GET_DB_VALUE)
{
//access database and get this value
}
}


So quite obviously the derived class would grow infinitely large based on the number of functions that I needed in my various programs that I would make using the button class. Question is, how to best ammend my button class to be able to incorporate such functionality i.e. assign a button to a function in any individual and unique program?