I'm using vc2008, writing some MFC code, I add a button, double click it, and vc2008 automatically create a callback function for me, and my code is like this:
void CDeviceTesterDlg::OnBnClickedButton1()
{
try {
....
} catch (std::exception &e) {
....
};
}
the problem is, I need place this ugly code in every OnBnClickedButtonXXX function,
are there any good method only place the code in one place?
A example in PyQt, I use this method:
def excepthook(type, value, traceback):
QMessageBox.warning(None, "", "%s: %s" % (str(type), str(value)))
return sys.__excepthook__(type, value, traceback)
sys.excepthook = excepthook
You can try using Structured Exception Handling. This is not equivalent to try/catch but it's similar to your PyQt example.
Related
I'm trying to update a label value from a background thread. I understand that there are several example, but I'm still having trouble understanding why the below code throw an stack overflow error. It seems like every time setTitle() is executed it goes through the true part of the if statement.
Set title Function:
void setTitle(char data[])
{
String^ temp = gcnew String(data);
if(this->lastSeen1->InvokeRequired)
{
setTitleDelegate^ d = gcnew setTitleDelegate(this, &setTitle);
d->Invoke(data);
}else
{
this->lastSeen1->Text = temp;
this->lastSeen1->Visible = true;
}
}
delegate:
delegate void setTitleDelegate(char data[]);
Thank you
Well, because of this:
d->Invoke(data);
See, here you're calling Delegate::Invoke, which basically means that setTitle just calls itself immediately. You need to call Control::Invoke instead, so you need to call it on an instance of Control, something like this:
this->lastSeen1->Invoke(d, /* any args here */);
I don't know why you're passing a char[] here, it's better not to mix native and managed data structures too much, if you can then just use String^ instead (but even then, C++/CLI isn't really meant for UI development either...).
I'm developing a code using Qt library in visual studio.
I have a class A as Child of Qt classes.
class A::A(QWidget *parent, QGLWidget *shareWidget)
: QGLWidget(parent, shareWidget)
one of the member function of this class is:
void A::setImage(Image *image)
{
m_image = image;
setFixedSize(image->width(), image->height());
}
(in which setFixedSize is a method of the parent class QWidget)
this method is called in the following event from another class:
bool B::event(QEvent* e)
{
QWidget::event(e);
...
A instA = new A();
instA.setImage(*image)
...
}
the following exception is thrown at setFixedSize, although the passed values are really normal int like width = height = 500.
Unhandled exception at 0x54A6B056 (Qt5Widgetsd.dll):
0xC0000005: Access violation reading location 0x939394BC.
this method setImage ist called several time while runing the code, and it works just great. The problem apears only in B::event(QEvent* e).
PS: The method is not working at this point, even if I pass directly the constant values like setFixedSize(500, 500).
Looking forward to any suggestion.
A instA = new A();
instA.setImage(*image)
This looks absurd to me. Can you please give exact compiled code.
Second, while using pointers pls make sure they are not null
So your function should be like this-
void A::setImage(Image *image)
{
if(image) //Null check, it will enter to block only if image is not null
{
m_image = image;
setFixedSize(image->width(), image->height());
}
}
I am working on developing a Qt application for windows platform. I am facing problem when using exception handling in class hierarchy.
I have Class B object instantiated in a function of Class A. When, due to some reason, an exception is thrown from Class B (and not caught in Class B) it is not being caught in Class A (appropriate try-catch block is present in Class A) and instead the application crashes showing some windows specific error. This type of try-catch mechanism in class hierarchy works perfectly fine in Java.
Example:
This is piece of code of ClassA that is instatiating an object of ClassB (Qt Dialog)
void Class A::on_pbCallB_clicked()
{
try
{
objClassB = new ClassB();
objClassB->show();
}
catch(QString *strExceptionMsg)
{
QMessageBox::critical(this,"Error",*strExceptionMsg);
exit(1);
}
catch(...)
{
QMessageBox::critical(this,"Error","Uknown Error");
exit(1);
}
}
When ClassB dialog is displayed and a button present on the dialog is pressed following piece of code is called:
void ClassB::on_pbThrowExp_clicked()
{
try
{
throw (new QString("Throwing Exception !"));
}
catch(QString *strExceptionMsg)
{
throw strExceptionMsg;
}
catch(...)
{
throw (new QString("Unknown Error"));
}
}
This throws an exception which is caught in ClassB's function but when thrown further it is not caught in ClassA (From where objClassB is instantiated) and the entire application crashes.
I have tried 1 solution where I have re-implemented QApplication’s notify method where, an exception thrown from somewhere in the application, if not caught anywhere, is being caught in re-implemented notify method. But doing this does not stop the application from closing down.
Please confirm if this is even possible in Qt/C++ and if not please point me in direction of an alternative (if available) in Qt.
This is an old question, but since there still might be people trying to combine Qt with exception handling, following is a solution that worked for me. It requires c++11 support though.
application.hpp:
#ifndef APPLICATION_HPP
#define APPLICATION_HPP
#include <QApplication>
#include <exception>
///
/// This class catches any exceptions thrown inside proc()
/// and shows them using the message() function.
/// The virtual message() function can be overriden to customize
/// how the messages are shown. The default implementation
/// shows them using QMessageBox.
///
class Application: public QApplication
{
public:
Application(int& argc, char* argv[]);
bool notify(QObject* receiver, QEvent* event);
virtual int proc() { return exec(); }
int run();
virtual int message(const std::string&);
private:
std::exception_ptr _M_e = nullptr;
};
#endif // APPLICATION_HPP
application.cpp
#include "application.hpp"
#include <QMessageBox>
Application::Application(int& argc, char* argv[]):
QApplication(argc, argv)
{ }
int Application::run()
{
try
{
int code = proc();
// Check if an exception was thrown and stored in Application::notify
// and if so, rethrow it.
if(_M_e) std::rethrow_exception(_M_e);
return code;
}
catch(std::exception& e)
{
return message(e.what());
}
}
int Application::message(const std::string& message)
{
QMessageBox::critical(0, "Error", QString::fromStdString(message));
return 1;
}
///
/// Qt does not allow exceptions thrown from event handlers
/// to be processed outside the event loop.
/// So we catch them here, store them in _M_e
/// and tell the application to exit.
///
bool Application::notify(QObject* receiver, QEvent* event)
{
try
{
return QApplication::notify(receiver, event);
}
catch(...)
{
_M_e = std::current_exception();
exit();
}
return false;
}
You can use the Application class as you would the QApplication, except call the run function instead of exec. (Alternatively, rename run into exec to hide QApplication's exec.)
You can override the message function to customize error messages. You can also override the proc function to add some initialization/destruction code before/after exec.
Well I have this code in my Managed C++/Cli in Visual Studio 2008, I want to be able to access the windows forms items inside of the callback of the Thread Function, and I can't, it generates an error.
Is there another way to do that? to be able to modify the GUI stuff inside of a method of the WinForms Class by using the Thread function callback ?
This example shows what I want to do.
I need to use a thread because I want to have the other things in the Forms to be accessible, and without using threads everything just freezes until everything is done, and the "Login" function it calls, takes some time because it does HTTP Requests. and after this HTTP Request I set the values that I got from it in a Form Element.
void Login(){
this->btn_next->Enabled = false;
this->login_accounts_facebook->Enabled = false; //This gives an error probably because of accessing "this->"
if(this->clb_contas->CheckedItems->Count <= 0){
//...
}
}
System::Void test_login_Click(System::Object^ sender, System::EventArgs^ e) {
ThreadStart^ start = gcnew ThreadStart(this, &Login_Test::Login);
Thread^ t = gcnew Thread(start);
t->Start();
}
Does anybody know how could I do that? if you think this can't be done and you want to suggest something something to make the GUI available while doing the process, I'm open for suggestions.
I hope I was being clear enough.
Thanks in advance.
All UI related code should be executed on the UI thread. In your case, that means that only the code you denoted with //... should be run on a separate thread. Extract that long-running code in its own method and pass that method to ThreadStart instead of Login(). Then you'll need to arrange for a way for the worker thread to notify the UI thread if and when it's complete.
Update:
Here's a crude example of how to modify your code. I would prefer to extract the long running operation in its own class if it is of sufficient complexity, but I think you get the idea.
The call to BeginInvoke ensures that LongRunningOperationComplete will be executed on the form's UI thread. You can use the same approach to call other methods that update the UI to indicate progress, even while the time-consuming operation is still running. If those methods require more parameters, you can create different delegates with the appropriate signature, and pass those parameters in the call to BeginInvoke. See here for how to do that.
// Same signature as LongRunningOperationComplete
delegate void MyInvokeDelegate();
void LongRunningOperation() {
for (int i=0; i < 100; i++) {
Thread::Sleep(100);
// The actual work that you're doing
}
// Operation complete. Update UI.
this->BeginInvoke(gcnew MyInvokeDelegate(this, &Login_Test::LongRunningOperationComplete));
}
void LongRunningOperationComplete() {
this->btn_next->Enabled = true;
this->login_accounts_facebook->Enabled = true;
}
System::Void StartMyLongRunningOperation() {
ThreadStart^ start = gcnew ThreadStart(this, &Login_Test::LongRunningOperation);
Thread^ t = gcnew Thread(start);
t->Start();
}
void Login() {
this->btn_next->Enabled = false;
this->login_accounts_facebook->Enabled = false; //This gives an error probably because of accessing "this->"
if(this->clb_contas->CheckedItems->Count <= 0){
StartMyLongRunningOperation();
}
}
System::Void test_login_Click(System::Object^ sender, System::EventArgs^ e) {
Login();
}
I'm trying to use a custom event in my WxWidgets C++ application, like described here.
In the constructor of my wxApp:
Connect(wxID_ANY, wxCommandEventHandler(APP::OnMyEvent));
Then the function that should catch the event:
void APP::OnMyEvent(wxCommandEvent& event)
{
exit(0); //testing
}
Finally, to test it:
wxCommandEvent MyEvent(wxEVT_COMMAND_BUTTON_CLICKED);
wxPostEvent(this, MyEvent);
I launch the thing...but it seems that the event is not posted or not caught.
Does someone understand this behaviour ?
You appear to be using the following overload of Connect:
void Connect(wxEventType eventType, wxObjectEventFunction function,
wxObject* userData = NULL, wxEvtHandler* eventSink = NULL)
If so, then should an event of type wxID_ANY happen (never?), then the connected function will be called.
Perhaps you need:
Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(APP::OnMyEvent));