Signal and slot Qt - c++

I’m trying to write a very simple calendar program (I’m trying to learn Qt). The program itself is very basic, all it does is open a dialog box which displays today’s date with a button next to it. When the button is pressed another dialog opens, which I’ll call the calendar picker.
Here is the gist of the program: First, the main dialog opens with the current date. Then when the button shown in the picture is pushed, a signal is sent to a function which opens the picker and sets up a connection between the two classes which I'll describe below! The picker opens in which you can choose a date if you want. Let's say you choose a date by double clicking it. A signal is then sent to a function which closes the picker and the function then emits a signal to the main dialog to update the date to the new date. Now here's the problem:
Both the main dialog and the picker are in separate classes and I'm trying to set up a connection between the two classes when an item is double clicked.
***EDIT: Ok, now my problem is that I have Picker *mypicker declared in my header file and when I try using it in the .cpp file for example mypicker->show(); it causes the program to crash. Anyone know why?
Any help would be appreciated!!

undefined reference to MainDialog::updateDate(QDate)
Usually means that the compiler or the linker can't find the reference to it. So in your header, you make a promise that it will exist.
Then if when matching things up later the reference was never found... you get an error.
So what probably happened is one of a few things:
In your maindialog.cpp file you have:
// Either no definition of updateDate at all, Wrong because you put in your header a declaration for one.
void updateDate(QDate date) // Wrong because it doesn't specify MainDialog
{
}
void MainDialog::updateDate() // Wrong because it doesn't match the parameter list
{
}
void MainDialog::updatedate(QDate date) // Wrong because the function name is off
{
}
QDate MainDialog::updateDate(QDate date) // Wrong because return type is off
{
}
void MainDialog::updateDate(QDate date) // Correct! Matches the header file perfectly!
{
}
Then after you get past that, and other compile errors, keep an eye on the Application Output, because the connect call is a runtime connection, so it won't report a syntax mis-alignment until at the moment a connection is attempted.
Hope that helps.

Related

QT Exception treatment

I've been trying to make a list in Qt that adds and removes integers for my Data Structures class, the teacher asked for a GUI, but I've been struggling a bit with the exception. I have managed to show the error when the list is empty, but the program closes after that, I wanted it to keep running after the warning popup window, but i have no idea how to proceed. I'm using try and catch to do that. Here is one of my remove buttons, this one removes the first int of the list.
void MainWindow::on_removerInicio_clicked()
{
try
{
throw ListaSeq.isEmpty();
}
catch(...)
{
QMessageBox::warning(this,tr("Aviso!"),tr("Lista Vazia!"));
}
ui->listWidget->takeItem(0);
ListaSeq.removeFirst();
nElementos--;
ui->nElementos->setText(QString::number(nElementos));
}
I know it's wrong but I don't know how to fix it, when clicked it shows the warning, but also closes the program. Can you help me?
Edit: Also if i take out the code
ui->listWidget->takeItem(0);
ListaSeq.removeFirst();
nElementos--;
ui->nElementos->setText(QString::number(nElementos));
The programs works fine and return to the mainwindow.

JUCE - Making a New Window

Coming from making single-page applications with the visual WYSISWYG editor in JUCE, I'm having a bit of trouble figuring out how to invoke new windows (outside of the main GUI window). I made a test application that just has a small minimal main GUI that I created with the visual editor. It has a button "Make New Window." My goal is to be able to click that button and have a new window pop up and that this new window is a JUCE "GUI component," (AKA, the graphical / visual GUI editor file). Now, I actually have sort of achieved this, however, its throwing errors and assertions, so it would be great to get a very simple, step-by-step tutorial.
I studied the main.cpp file that the Projucer automatically created in order to get a feel for how they are creating a window. Here's what I did.
1) In my project, I added a new GUI Component (which becomes a class) and called it "InvokedWindow."
2) In my main GUI component class header, I added a new scoped pointer of type InvokedWindow: ScopedPointer<InvokedWindow> invokedWindow;
3) I created a new button in the main GUI editor called "Make New Window" and added this to the handler code:
newWindowPtr = new InvokedWindow; so that any time the button is hit, a new object of type InvokedWindow is created.
4) In the InvokedWindow class, in the constructor, on top of the automatically generated code, I added:
setUsingNativeTitleBar (true);
setCentrePosition(400, 400);
setVisible (true);
setResizable(false, false);
Which I sort of got from the main file of the JUCE application.
I also added a slider to this new window just to add functionality to it.
5) I added an overloaded function to let me close the window:
void InvokedWindow::closeButtonPressed()
{
delete this;
}
So, now when I run the app and click the make new window button, a new window does pop up, but I get an assertion:
/* Agh! You shouldn't add components directly to a ResizableWindow - this class
manages its child components automatically, and if you add your own it'll cause
trouble. Instead, use setContentComponent() to give it a component which
will be automatically resized and kept in the right place - then you can add
subcomponents to the content comp. See the notes for the ResizableWindow class
for more info.
If you really know what you're doing and want to avoid this assertion, just call
Component::addAndMakeVisible directly.
*/
Also, I'm able to close the window once and hit the button in the main GUI to create another instance of a newWindow, but closing it a second time leads to an error:
template <typename ObjectType>
struct ContainerDeletePolicy
{
static void destroy (ObjectType* object)
{
// If the line below triggers a compiler error, it means that you are using
// an incomplete type for ObjectType (for example, a type that is declared
// but not defined). This is a problem because then the following delete is
// undefined behaviour. The purpose of the sizeof is to capture this situation.
// If this was caused by a ScopedPointer to a forward-declared type, move the
// implementation of all methods trying to use the ScopedPointer (e.g. the destructor
// of the class owning it) into cpp files where they can see to the definition
// of ObjectType. This should fix the error.
ignoreUnused (sizeof (ObjectType));
delete object;
}
};
This is all a bit over my head. I was figuring it wouldn't be too bad to be able to create a new window, via a button. A new window that I could edit with the graphical GUI editor, but I'm not able to fully figure it out all on my own, through I did try. Could anyone post a step-by-step guide to doing this the correct way? I did post this at the JUCE forums, but due to my lack of GUI programming, I was unable to understand the solutions posted (my own fault), so I'm hoping to get a very simple guide to this. It would be very much appreciated. Thank you.
I figured it out. I needed to create:
A new GUI component (Remember, this is the visual editor in JUCE)
A class (I called it BasicWindow, based on the JUCE demo code) that acts as a shell to run this new window and holds the GUI component.
A JUCE SafePointer that makes a new object of type BasicWindow whenever the button is clicked and sets the attributes to that window.
Here is my code:
Referring to line 3) Inside the handler section of the button to create the new window:
basicWindow = new BasicWindow("Information", Colours::grey, DocumentWindow::allButtons);
basicWindow->setUsingNativeTitleBar(true);
basicWindow->setContentOwned(new InformationComponent(), true);// InformationComponent is my GUI editor component (the visual editor of JUCE)
basicWindow->centreWithSize(basicWindow->getWidth(), basicWindow->getHeight());
basicWindow->setVisible(true);
Referring to line 2) A .cpp file that defines what the BasicWindow is:
#include "../JuceLibraryCode/JuceHeader.h"
class BasicWindow : public DocumentWindow
{
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BasicWindow)
public:
BasicWindow (const String& name, Colour backgroundColour, int buttonsNeeded)
: DocumentWindow (name, backgroundColour, buttonsNeeded)
{
}
void closeButtonPressed() override
{
delete this;
}
};
And referring to line 1) Make the GUI editor component, which this is easy to do. You just right add a new file in the JUCE file manager. "Add New GUI Component," then visually add all your elements and handler code.
My biggest issue was that I was using a JUCE ScopedPointer, so after deleting the object, the pointer pointing to it wasn't being set back to NULL. The SafePointer does this. If any more explanation is needed, I'm happy to help, as this was terrible for someone with not much GUI development "under his belt."

Qt: How to change QWizard default buttons

I'm making a program with Qt 4.8.5 on a Fedora system (unix). It's a QWizard structure with its QWizardPages.
I needed to change the default QWizard buttons (back, next, finish...) and customize it. I found I could do it putting the next lines on the constructor of my QWizard class called BaseWizard (class BaseWizard : public QWizard)
QList<QWizard::WizardButton> button_layout;
button_layout <<QWizard::Stretch << QWizard::CustomButton1 << QWizard::BackButton << QWizard::NextButton << QWizard::FinishButton;
this->setOptions(QWizard::NoDefaultButton);
With that what I have from left to right is one custom buttons, the back button, the next button and the finish button, and when I want I can show or hide the custom buttons with SetVisible() / SetDisabled() / setEnabled() functions.
That worked perfect for what I wanted until now... I have to make some changes to the program so I need to change those buttons depending on the page the user is. As I said before, I know I can change the visibility of CustomButton 1 for example BUT I can't do the same with back button so... my quesiton is: How can I decide which buttons I show in every QWizardPage (and their text) and which is the best way to do it?
I've tried creating a function on my BaseWizard
// Function to have only 2 custom buttons
void BaseWizard::ChangeButtons()
{
QList<QWizard::WizardButton> button_layout;
button_layout <<QWizard::Stretch << QWizard::CustomButton1 << QWizard::CustomButton2;
setButtonLayout(button_layout);
}
And then in the QWizardPage (lets call it WP) using it like:
BaseWizard *bz;
bz->ChangeButtons();
But when I do that nothing changes.I can still see the NextButon for example. I have tried also using first a button_layout.clear(); to see if clenaing it before adding the buttons works, but not.
I have also tried changing the text of CustomButton1. If I do it in the WP after calling ChangeButtons with
wizard()->button(QWizard::CustomButton1)->setText("TEXT CHANGED");
Then the text changes but if I put it in the ChangeButton() function with this->button(QWizard::CustomButton1)->setText("BBBBB"); it does nothing (But its entering into the funcion). Ofc if I try to change the text of CustomButton2 in WP nothing happens because I can't still see that button... so any idea of what I am doing wrong or how could I get what I try will be very apreciated,
Thank you so much.
Ok, I finally knew why was my program crashing... I put here the solution if anyone needs it in the future:
BaseWizard *bz; // <-- HERE is the problem
bz->ChangeButtons();
I was not initializing the pointer so it has to be changed to:
BaseWizard *bz = dynamic_cast<BaseWizard*>(wizard());

CheckBox value in different file

I need to access the checkbox value in a different program. Check box is initiated in ToolDlg.cpp
DDX_Control(pDX, IDC_CalculateTBA, m_CalculateTBA);
in the oninitdialog initiated like this:
m_CalculateTBA.SetCheck(0);
CalculateAnalyticTBA = false;
void CToolDlg::OnBnClickedCheck3()
{
CalculateAnalyticTBA = m_CalculateTBA.GetCheck();
}
I need checkbox value in SetCal.cpp program. Here is the code i am trying in this program:
CToolDlg dialog;
if( dialog.CalculateAnalyticTBA )
{
Do some thing
}
But the dialog.CalculateAnalyticTBA is always tru even though i don't check the check box.
Plz let me know if you need any other info. Thanx for help.
It looks like you're creating a dialog, and never showing it. So CalculateAnalyticTBA has whatever value you gave it in the constructor of your CToolDlg class (or, if you didn't, whatever value the compiler gave it).
In order for this value to be set you must at least create the dialog so that the Data Exchange code (which invokes the DDX_Control and handles the binding of the checkbox and the variable) has a chance to run.
The correct way is to create and display the CToolDlg dialog and wait for the user to select his choices then only process the choices when the user finally click the "OK" button.
CToolDlg dialog;
// create and display the dialog
if (dialog.DoModal()==IDOK)
{ // user clicked the ok button, now do the work
....
}

Weird bug in Qt application

In my application, I have my re-implemented QGraphicsView checking for a mouseReleaseEvent(), and then telling the item at the position the mouse is at to handle the event.
The QGraphicsItem for my view is made up of two other QGraphicsItems, and I check which one of the two is being clicked on (or rather having the button released on), and handle the respective events.
In my Widget's constructor, I set one of the items as selected by default, using the same methods I used when the items detect a release.
When I debugged, I found that for the LabelItem, select is called without a problem from the constructor (and the result is clear when I first start the application). But, when I click on the items, the application terminates. I saw that I was getting into the select function, but not leaving it. So the problem is here.
Which is very weird, because the select function is just a single line setter.
void LabelItem::select()
{
selected = true;
}
This is the mouseReleaseEvent;
void LayerView::mouseReleaseEvent(QMouseEvent *event)
{
LayerItem *l;
if(event->button() == Qt::LeftButton)
{
l = (LayerItem *) itemAt(event->pos());
if(l->inLabel(event->pos()))
{ //No problem upto this point, if label is clicked on
l->setSelection(true); //in setSelection, I call select() or unselect() of LabelItem,
//which is a child of LayerItem, and the problem is there.
//In the constructor for my main widget, I use setSelection
//for the bottom most LayerItem, and have no issues.
emit selected(l->getId());
}
else if(l->inCheckBox(event->pos()))
{
bool t = l->toggleCheckState();
emit toggled(l->getId(), t);
}
}
}
When I commented the line out in the function, I had no errors. I have not debugged for the other QGraphicsItem, CheckBoxItem, but the application terminates for its events as well. I think the problem might be related, so I'm concentrating on select, for now.
I have absolutely no clue as to what could have caused this and why this is happening. From my past experience, I'm pretty sure it's something simple which I'm stupidly not thinking of, but I can't figure out what.
Help would really be appreciated.
If the LabelItem is on top of the LayerItem, itemAt will most likely return the LabelItem because it is the topmost item under the mouse. Unless the LabelItem is set to not accept any mouse button with l->setAcceptedMouseButtons(0).
Try to use qgraphicsitem_cast to test the type of the item. Each derived class must redefine QGraphicsItem::type() to return a distinct value for the cast function to be able to identify the type.
You also could handle the clicks in the items themselves by redefining their QGraphicsItem::mouseReleaseEvent() method, it would remove the need for the evil cast, but you have to remove the function LayerView::mouseReleaseEvent() or at least recall the base class implementation, QGraphicsView::mouseReleaseEvent(), to allow the item(s) to receive the event.
I have seen these odd behaviours: It was mostly binary incompatibility - the c++ side looks correct, and the crash just does not make sense. As you stated: In your code the "selected" variable cannot be the cause. Do you might have changed the declaration and forgot the recompile all linked objects. Just clean and recompile all object files. Worked for me in 99% of the cases.