I am quite new to C++ and Qt. I've gotten pretty far on my current project, but I've been putting off this one part. I have a pushbutton that opens a new dialog like this:
void MainWindow::on_fillAll_clicked()
{
int yo;
BlockSelect bSelect;
bSelect.setModal(true);
bSelect.exec();
if( bSelect.exec() == QDialog::Accepted )
{
//Get stuff here?
//I want to fill yo with the spinbox value
yo = bSelect.stuff();
return;
}
qDebug() << yo;
}
This works fine. In the dialog I have a spin box. I want to send that value inputted to the spin box to my main window when the user clicks OK.
I have been trying to get "int yo;" to have that value from the spinbox but everything I try just gets an error.
I added this to my BlockSelect public class:
int stuff();
And I made this function in my blockselect.cpp:
int BlockSelect::stuff()
{
qDebug() << "The function was called";
return ui->yolo->value();
}
But qDebug never shows anything???
So how can I fill yo from the main window with yolo from the dialog?
Sorry if I didn't explain this well :( I'm still learning.
Thanks for your time :)
First of all, there is no need to call exec() twice, just use it once within the if statement.
To answer your question, you still have the bSelect dialog object (and I'm assuming BlockSelect is a class you define?), so make an accessor function inside it to retrieve the values you want.
if( bSelect.exec() == QDialog::Accepted )
{
//Get stuff here?
//I want to fill yo with the spinbox value
yo = bSelect.stuff();
return;
}
EDIT:
Your BlockSelect class needs to contain an accessor function, this means a function that returns a value.
int stuff() { return ui->yolo->value();}
What I'm doing here is retrieving the spinbox's value (assuming it is named 'yolo') and returning it as a result of calling the 'stuff' function.
Related
Good time of day! I have a question you'll maybe find silly and obvious, but i've already broke my head trying to solve this.
I want to plot some curve by pressing a QPushButton. I wrote the slot and connected it to the corresponding signal of this button. But when I click on it, nothing happens on the plot, although this function executes, and it can be viewed on the debugger and qDebug() output.
On the other hand, if you call this function directly, and not as a slot, it works perfectly. The only difference is the calling method: as a slot in first case and as a method in the second case.
Some code examples:
//Slot
void MainWindow::buttonClick()
{
qDebug() << "Enter";
XRDDataReader *xrdr = new XRDDataReader();
xrdr->fromFile("/home/hippi/Документы/Sources/Qt/49-3.xy");
ui->plot->plotXRD(xrdr->xValues(), xrdr->yValues());
qDebug() << "Quit";
}
void Plotter::plotXRD(QVector<double> x, QVector<double> y)
{
QwtPlotCurve *curve = new QwtPlotCurve();
curve->setRenderHint
( QwtPlotItem::RenderAntialiased, true );
curve->setPen(Qt::black, 2);
curve->setSamples(x,y);
curve->attach(mainPlot);
}
As long as autoreplotting is not enabled, you have to call replot to make changes happen.
In my project, I have a listWidget. When the user clicks an item in the list, it loads this:
void BlockSelect::on_blockList_clicked(const QModelIndex &index)
{
QString blockListName;
QString temp_hex;
QString temp_hex2;
int temp_int;
QListWidgetItem *newitem = ui->blockList->currentItem();
blockListName = newitem->text();
temp_hex = blockListName.mid(0, blockListName.indexOf(" "));
if(temp_hex.indexOf(":") == -1)
{
temp_int = temp_hex.toInt();
ui->blockIdIn->setValue(temp_int);
ui->damageIdIn = 0;
}
else
{
temp_hex2 = temp_hex.mid(temp_hex.indexOf(":")+1, temp_hex.length()-(temp_hex.indexOf(":")+1));
temp_hex = temp_hex.mid(0, temp_hex.indexOf(":"));
temp_int = temp_hex.toInt();
ui->blockIdIn->setValue(temp_int);
temp_int = temp_hex2.toInt();
ui->damageIdIn->setValue(temp_int);
}
}
Most of this is just string manipulation. (You don't have need to study this syntax or anything)
My problem is, when the user clicks on another list item quickly (Before this current process is finished) the program crashes. Is there any way to allow fast clicks (multiple processes at once) or maybe an alternative solution?
Thanks for your time :)
I hope that you execute all this code in the GUI thread. If so, then there will be no problem - if your code were correct (it isn't). There is no such thing as the "process" that you mention in your question. The clicks are handled by a slot, and they are invoked from an event handler within the list. This is not supposed to crash, and the clicks will be handled in a serialized fashion - one after another.
Here's the bug: Why do you reset the value of an allocated UI pointer element to zero?
ui->damageIdIn = 0;
This is nonsense. Maybe you mean to ui->damageIdIn->setValue(0) or ui->damageIdIn->hide(). You then proceed to use this zero value in
ui->damageIdIn->setValue(temp_int);
and it crashes.
You may also have bugs in other places in your code.
What I'm trying to do
I am trying to create a subclass of QWizardPage that looks somewhat like this,but has a slight tweak. I want to disable the next button when a counter variable is more than 0. (It can't be 0 from the get-go due to some functionality that requires it to go x..x-1...0).
What I've tried
Reimplement isComplete() and emit completeChanged() in the constructor
bool DemoWizardPage::isComplete()
{
return ! (counter > 0); //Also tried just return false;
}
Reimplement initializePage and disable the next button from there
void DemoWizardPage::initializePage()
{
qDebug() << "QWizardPage:: initialize page";
if (!this->isComplete())
{
qDebug() << "try to turn off next button";
wizard()->button(QWizard::NextButton)->setDisabled(true);
qDebug() << "next button enabled? "
<< wizard()->button(QWizard::NextButton)->isEnabled();
}
}
Results so far
From stepping through the code I can see that the next button is disabled when the page loads. But then it is enabled again due to these 2 lines in QWizardPrivate (taken from qwizard.cpp)
bool complete = page && page->isComplete();
btn.next->setEnabled(canContinue && complete);
I am quite baffled as to why isComplete() is returning true here. I mean, I set my counter to be 2 at the beginning and I never decrease it. (And yes, I do emit a completeChanged() whenever I set the counter).
Any ideas?
QWizard automatically manages the state of Next button based on the QWizardPage::isComplete(), you should not implement that functionality yourself in initializePage(). The reason your isComplete() is not being called is that it doesn't actually overwrite QWizardPage::isComplete const from QWizardPage. Declare your function const and it will properly overwrite the original function.
I m trying to make a media player . The time status of the track is shown using QSlider. Track seek should happen when the user releases the slider somewhere on the QSlider. I had a look on the list of QSlider signals. The one that seems to fit is sliderReleased() which happens when the user releases the slider, but it does not get the latest value of where slider is. So to get sliders latest value I used sliderMoved() and stored reference.
Signal and slot connection
connect(this->ui->songProgress, SIGNAL(sliderMoved(int)), this,
SLOT(searchSliderMoved(int)));
connect(this->ui->songProgress, SIGNAL(sliderReleased()), this,
SLOT(searchSliderReleased()));
Functions
void MainWindow::searchSliderMoved(int search_percent)
{
value=this->ui->songProgress->value();
std::cout<<"Moved: Slider value"<<value<<std::endl;
}
Now I am Using the "value" variable inside searchSliderReleased for seeking
void MainWindow::searchSliderReleased()
{
std::cout<<"Released: Slider value"<<value<<std::endl;
emit search(value);//seek the track to location value
}
But the problem with above technique is that sliderMoved signal does not give the value where the slider is dropped but it give the location from where the slider was moved. How do I obtain the value where the slider was dropped?
You can use the valueChanged(int) signal of the slider, but set the flag
ui->horizontalSlider->setTracking(false);
Just finished building a DiectShow media player with QSlider here at work. Here's a few slot snippets on how I did it.
Widget::sliderPressed()
{
if( isPlaying() )
{
m_wasPlaying = true;
pause();
}
else
{
m_wasPlaying = false;
}
// Set a flag to denote slider drag is starting.
m_isSliderPressed = true;
}
Widget::sliderReleased()
{
if( m_wasPlaying )
{
play();
}
m_wasPlaying = false;
m_isSliderPressed = false;
}
Widget::valueChanged( int value )
{
if( m_isSliderPressed )
{
// Do seeking code here
}
else
{
// Sometime Qt when the user clicks the slider
// (no drag, just a click) Qt will signals
// pressed, released, valueChanged.
// So lets handle that here.
}
}
Had the same problem and calling sliderPosition() instead of value() directly when handling sliderReleased() worked for me.
I prefer to save the last value set by our app, like this pseudocode:
// Save our last value
lastSoftwareVal = 0;
// Set value from program
slider_set_value(value){
lastSoftwareVal = value;
slider.setValue(value)
}
// Slider on change callback
slider_on_change(value){
if(value == lastSoftwareVal){
// Value was changed by our app
return false;
}
// User has changed the value, do something
}
Firstly i make a program for showing table in wxListCtrl, it worked but for limited amount of data..
it shows a problem like:-
when i execute the program . frame do the visible after some time... but it works
then i turns to use wxThread now everthing is going fine, now when i execute the program frame immediately visible because i write Sleep(1000), so it add a line in wxListCtrl one by one , but it is giving unexpected result depend upon how many rows are in database..
my code is:-
# include "thread.h"
# include "login.h"
# include "sql.h"
# include <mysql.h>
class List_Ctrl_Data;
MyThread :: MyThread(login* login_obj)
{
this->temp = login_obj;
}
void *MyThread :: Entry()
{
int i=1,j,k=0 ;
while(i!=100)
{
long index=this->temp->data_list_control->InsertItem(i,wxT("amit"));
for(j=1;j<3;j++)
{
this->temp->data_list_control->SetItem(index,j,wxT("pathak"));
}
k++;
if(k==1)
{
k=10;
this->Sleep(1000);
}
i++;
}
}
here data_list_control is the object of wxListCtrl , with the help of thread i m filling value inside the wxListCtrl.
some people advised me that here u r knocking frame control( wxListCtrl) again and again from thread entry ,
thats why frame getting hanged you should use wxPost or AddPendingRequest for this, i dont think that it would work,
i tried to explain you my prob, still u feel to ask anything , u r welcome.. if you will help me, it would be a lot for me
The problems you are seeing are likely due to the fact that you are calling methods on a GUI control from a secondary thread rather than the main thread. This should never be done. You need to add the items from the main thread.
I'm guessing one of the reasons you have attempted to do this from a secondary thread is because it takes too long to add large number of items, and it's hanging your user interface. The correct approach is either to use a virtual list control (as noted in the "duplicate" question #Erik mentioned), or to periodically call wxYield (or wxSafeYield) while adding items so that UI events are processed.
********************************SOLUTION IS HERE******************
i used the code in thread like[ it get a row from database and pass to event]
void *MyThread :: Entry()
{
List_Ctrl_Data obj1 ;
MYSQL_RES *database_table_data;
database_table_data=obj1.getdata();
MYSQL_ROW row;
while((row=mysql_fetch_row(database_table_data))!=NULL)
{
wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, 100000 );
void *row_data;
row_data=(void *)row;
event.SetClientData(row_data);
temp->GetEventHandler()->AddPendingEvent( event );
this->Sleep(1000);
}
}
and for handling this we create a event table and a function to handle this value-
void onNumberUpdate(wxCommandEvent& evt);
private:
DECLARE_EVENT_TABLE()
in header file and in cpp file we write
void login::onNumberUpdate(wxCommandEvent& evt)
{
int i=0,j;
void* hold_row;
hold_row=(void *)evt.GetClientData();
MYSQL_ROW row;
row=(MYSQL_ROW)hold_row;
//while(row!=NULL)
//{
//wxPuts(wxT("kjhjkh"));
const char* chars1 = row[0];
wxString mystring1(chars1, wxConvUTF8);
long index=data_list_control->InsertItem(this->counter,mystring1);
this->counter++;
for(j=1;j<3;j++)
{
const char* chars2=row[j];
wxString mystring2(chars2,wxConvUTF8);
data_list_control->SetItem(index,j,mystring2);
}
//}
}
BEGIN_EVENT_TABLE(login, wxFrame)
EVT_COMMAND (100000, wxEVT_COMMAND_TEXT_UPDATED, login::onNumberUpdate)
END_EVENT_TABLE()
and finally i got the solution of my problem//////
www.rohitworld.site90.net OR ROHITAMITPATHAK#GMAIL.COM