Qt connect crash when using lambda function - qt

Code is here
void A::fun()
{
QAction* act = new QAction(this);
QAction* act2 = new QAction(this);
connect(act, QAction::triggered, [this, &act2]() {...; act2.setDisable(true);}
// crash when &act2 is used to capture the variable
// but it is okay using act2 to capture the variable
}
What is the reason? Thanks.

You are taking a reference of act2 even though it is a pointer that will go out scope, that is why copying the pointer works.

Related

QT connect function using lambda

I have a list with buttons , everyone has a name (str1 is the QString var with the name) and I want to connect them with a function with parameter but i don't understand how to do this.
QPushButton *btn = new QPushButton(str1);
connect(btn,SIGNAL(clicked()),this,SLOT(activeProjectClick()));
this is what i can do but here i can't use function with parameter. I read that i have to use the connect method with lambda but i don't understand exactly how to do this. Let's supose i want to call function F1(QString str) , how can i do this?
You can also use = to capture by value or use '&' capture by reference.
connect(btn,
&QPushButton::clicked,
this,
[=]
{
F1(str1);
};
I figured out , i have to declare the var inside []
alternatively, use & inside []
QString str;
for(QPushButton *btn : buttonsList) { connect(btn, &QPushButton::clicked, [&]({F1(str); });}

How to properly connect a QProgressBar with a QFutureWatcher?

I want the progress of the function to be displayed on progressBar. Following the guides, I wrote the code below. But during the execution of the function, the program freezes, then progress bar's value becomes equal to one.
The program itself will not produce errors. The result of the function is correct.
I think my problem is that I don’t know how to connect the value of the progress of a function with the value of a progress bar.
(Form.h)
public:
MyObject object;
QFutureWatcher<QBitArray> FutureWatcher;
QFuture<QBitArray> future;
(Form.cpp) Form constructor body:
ui->setupUi(this);
ui->progressBar->setMinimum(0);
ui->progressBar->setMaximum(100);
connect(&this->FutureWatcher, SIGNAL(progressValueChanged(int)), ui->progressBar, SLOT(setValue(int)));
(Form.cpp) Function on_button_clicked():
void Form::on_button_clicked()
{
QString message = ui->textEdit->toPlainText();
future = QtConcurrent::run(&this->object, &MyObject::longFunction, message);
this->FutureWatcher.setFuture(future);
QBitArray bitresult = future.result();
}
The problem is that you're immediately calling future.result(). The problem with this is that result() will wait until the QFuture has finished.
The Qt documentation says (https://doc.qt.io/qt-5/qfuture.html#result):
If the result is not immediately available, this function will block and wait for the result to become available.
The solution is to connect a slot to QFutureWatcher::finished():
auto *watcher = new QFutureWatcher<QBitArray>(this);
connect(watcher, &QFutureWatcher::finished, this, [=]() {
auto result = watcher->result();
// do something with the result
// important: delete watcher again
watcher->deleteLater();
});
// now start the task
QString message = ui->textEdit->toPlainText();
watcher->setFuture(QtConcurrent::run(myObject, &MyObject::longFunction, message));

how to update QTableWidget item?

There is a thread running! it receives data from internet two times per second, then I set the data in qtablewidget?
How can I make the QTableWidget update itself ?
Now I must click the interface if I want to update the display!
DWORD WINAPI MyThreadProc1(LPVOID lpParameter){
int data=receive();
w.setVal(data);
return 0;
}
void TradeSystem::setValue(int num){
QTableWidgetItem *item = new QTableWidgetItem(QString::number(num,10,1));
item->setBackgroundColor(QColor(0,60,10));
ui.tableWidget_3->item(0,0)->setText(QString::number(num,10,0));
}
i guess this problem falls in the category 'i want to change gui from another thread' -> don't do it.
when setValue(int) is a slot, you can do the following:
DWORD WINAPI MyThreadProc1(LPVOID lpParameter)
{
(void)lpParameter;
int data = receive();
QMetaObject::invokeMethod(w, "setValue", Q_ARG(int, data));
}
You should get used to signals in QT , its easy to use and can make your life easier .
DWORD WINAPI MyThreadProc1(LPVOID lpParameter){
int data=receive();
emit data_recieved(data);
return 0;
}
void TradeSystem::setValue(int num){
QTableWidgetItem *item = new QTableWidgetItem(QString::number(num,10,1));
item->setBackgroundColor(QColor(0,60,10));
ui.tableWidget_3->item(0,0)->setText(QString::number(num,10,0));
}
and before you activate MyThreadProc1 , connect the signal and handler :
connect(this,SLOT(setValue(int)),MyThreadProc1,SIGNAL(data_recieved(int)));
that way , you can connect basically every widget in qt with a signal/slot .
either in different Form,Threads .
This is helpful also Docs.

Reprinting a picking list to a printer and not to screen via X++

I am trying to automatically print a picking list directly to the printer. It has already been picked. Here is a job that prints it, but it keeps going to the screen and not to the printer.
static void JobReprintPickingList(Args _args)
{
Args args;
ReportRun reportRun;
SalesFormLetter salesFormLetter;
PrintJobSettings printJobSettings;
RecordSortedList list = new RecordSortedList(tablenum(WMSPickingRoute));
WMSPickingRoute wmsPickingRoute = WMSPickingRoute::find('PkR 079256');
;
if(!wmsPickingRoute)
return;
list.ins(wmsPickingRoute);
args = new Args(ReportStr(WMSPickingList_OrderPick));
args.designName("Standard");
printJobSettings = new PrintJobSettings();
printJobSettings.deviceName('HP Universal Printing PCL 6');
printJobSettings.setTarget(PrintMedium::Printer);
printJobSettings.preferredTarget(PrintMedium::Printer);
salesFormLetter = new SalesFormLetter_PickingList(false);
salesFormLetter.updatePrinterSettingsFormLetter(printJobSettings.packPrintJobSettings());
args.caller(salesFormletter);
args.parmEnum(PrintCopyOriginal::Original);
args.parmEnumType(enumnum(PrintCopyOriginal));
args.object(list);
reportRun = new ReportRun(args);
reportRun.init();
reportRun.run();
}
I figured out the answer. I had to add this line:
printJobSettings.lockDestinationProperties(true);
This force it to the printer anway.
You could change your code to use OriginalPrint like this :
args.parmEnum(PrintCopyOriginal::OriginalPrint);
The problem lies on the method loadPrintSettings of class FormLetterReport that overrides the target to screen when you use Original or OriginalCopy.

FileReference.download() not working

I'm building a Flex app which requires me to download files.
I have the following code:
public function execute(event:CairngormEvent) : void
{
var evt:StemDownloadEvent = event as StemDownloadEvent;
var req:URLRequest = new URLRequest(evt.data.file_path);
var localRef:FileReference = new FileReference();
localRef.addEventListener(Event.OPEN, _open);
localRef.addEventListener(ProgressEvent.PROGRESS, _progress);
localRef.addEventListener(Event.COMPLETE, _complete);
localRef.addEventListener(Event.CANCEL, _cancel);
localRef.addEventListener(Event.SELECT, _select);
localRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _securityError);
localRef.addEventListener(IOErrorEvent.IO_ERROR, _ioError);
try {
localRef.download(req);
} catch (e:Error) {
SoundRoom.logger.log(e);
}
}
As you can see, I hooked up every possible event listener as well.
When this executes, I get the browse window, and am able to select a location, and click save. After that, nothing happens.
I have each event handler hooked up to my logger, and not a single one is being called! Is there something missing here?
The problem seems to be with my command being destroyed before this could finish.
For a proof of concept, I set my localRef variable to be static instead of an instance variable, and everything went through successfully! I guess Cairngorm commands kill themselves asap!

Resources