qslider sliderReleased value - c++

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
}

Related

How do I assign a value in an array when a mouse is pressed SFML C++

I am trying to make a program where you are allowed to select between an option of shapes, and then drawing it. To allow for multiple shapes I created a vector of a class which creates shapes (Shapes are set up with the chosen function). My problem is the mouse click is too long, so it assigns it to everything in the vector, so you can't create a new shape. Is there a problem in my logic, or is there a problem in the code?
Here is my attempt:
for (auto& it : onCanvas) {
if (Mouse::isButtonPressed(Mouse::Left)) {
if (mousepointer.getGlobalBounds().intersects(circleOption.getGlobalBounds())) {
it.chosen(circles);
}
if (mousepointer.getGlobalBounds().intersects(rectOption.getGlobalBounds())) {
it.chosen(rectangle);
}
if (mousepointer.getGlobalBounds().intersects(triOption.getGlobalBounds())) {
it.chosen(triangles);
}
if (mousepointer.getGlobalBounds().intersects(it.shape.getGlobalBounds()) || it.dragging) {
it.shape.setPosition(mousepointer.getPosition());
it.dragging = true;
}
}
if (!Mouse::isButtonPressed) {
it.dragging = false;
}
win.draw(it.shape);
}
Your source-code is a bit incomplete (what is onCanvas and mousepointer). But I guess the problem is that this snippet is called multiple times while your mouse is clicked. To avoid that you can do two thing.
In the first solution you use events, so you only add shapes when the state of the mousebutton changes (you can additionally listen to the MouseButtonReleased to simulate a full click):
if (event.type == sf::Event::MouseButtonPressed)
{
if (event.mouseButton.button == sf::Mouse::Left)
{
// Hit Detection
}
}
or second solution you remember the last state of the button (probably do the mouse check once outside of the for loop):
bool mouse_was_up = true;
if (mouse_was_up && Mouse::isButtonPressed(Mouse::Left)) {
mouse_was_up = false;
for (auto& it : onCanvas) {
// Hit Detection
}
}
else if (!Mouse::isButtonPressed(Mouse::Left))
mouse_was_up = true;
I would rather stick to the first solution because when your click is too short and your gameloop is in another part of the game logic, you can miss the click.

Blocking signal one time in Qt doesn't work correctly

Hi i have following code:
void MainWindow::on_listWidgetNotes_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)//Test!
{
if(current != NULL)
{
ui->plainTextEditContent->setEnabled(true);
change = false;
if(isModified)
{
auto reply = QMessageBox::question(this, "Test", "Do you want save changes?", QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel);
if (reply == QMessageBox::Yes) on_pushButtonSave_clicked();
else if(reply == QMessageBox::No) notes.closeFile();
else
{
//ui->listWidgetNotes->blockSignals(true);
ui->listWidgetNotes->setCurrentItem(previous);
//ui->listWidgetNotes->blockSignals(false);
return;
}
}
isModified = false;
this->setWindowTitle(current->text()+" - VfNotes 1.0");
ui->plainTextEditContent->setPlainText(notes.openFile(current->text()));
}
}
In specified case code have to show message box and set focus on previous item, after select cancel button.
But setCurrentItem calls on_listWidgetNotes_currentItemChanged again with this message box. After use blockSignals focus doesn't come back on previous element. What to do to set focus on previous item after click cancel, that on_listWidgetNotes_currentItemChanged wasn't call again?
So, if this is the slot that gets called when the selection changes, then instead this slot getting called , create another slot and from there, you call this function..
Now this new slot will have the previous item and from there if the function returns a book instead of void signifying that a cancel is pressed, then you call setCurrentItem again...

C++ Break a loop from another function

I'm developing a video recording software but I am stuck on an issue.
I want to stop the recording when the button Stop is clicked but nothing happens when I click it...
Here is my core (simplified):
MySoftware.hpp:
bool b_Stop = false;
MySoftware.cpp
MainWindow::MainWindow() : QWidget() {
qpb_StartCapture = new QPushButton("Start Capture", this);
QObject::connect(qpb_StartCapture, SIGNAL(clicked()), this, SLOT(startCapture()));
qpb_StopCapture = new QPushButton("Stop Capture", this);
QObject::connect(qpb_StopCapture, SIGNAL(clicked()), this, SLOT(stopCapture()));
}
void MainWindow::startCapture() {
b_Stop = false;
// CAMERAS INITIALIZATION
while (!b_Stop) {
for (int i = 0; i < v_cp_Cameras.size(); i++) {
// IMAGE CAPTURE
}
}
// IMAGES PROCESSING
}
void MainWindow::stopCapture() {
b_Stop = true;
}
The way I see it is that startCapture is probably called from your event loop. This blocks any other events from being processed. Try putting your loop into a separate thread and see if that works.
You're having the image capture inside of a for loop that doesn't check whether or not the stop button is activated. You're checking the while loop, which probably never starts over. put if (b_stop) {break;} inside the for loop and it might work.

(Qt C++) Send int value from dialog to MainWindow?

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.

Problems creating progress bar in Visual Studio using MFC

i'm trying to simply fill a progress bar, full when a check box is checked, and empty when the box is unchecked. there is an ONCLICK action for the check box, so i figured i would check the value every time it was clicked, and would fill the bar only when it was checked.
this code includes a couple different things i tried, anything with progCtrl gave me a runtime error. any thoughts would be helpful, thanks!
void Cgui1Dlg::OnBnClickedsetkill()
{
// TODO: Add your control notification handler code here
//IDC_PROGRESS.Value = 100;
//CProgressCtrl progCtrl;
//progCtrl.SetDlgCtrlID(IDC_PROGRESS);
//UpdateData();
//if(changefill)
//{
//IDC_PROGRESS.PBM_SETPOS(100);
//SendMessage(IDC_PROGRESS, PBM_SETPOS, 100);
//progCtrl.SetPos(100);
//}
//else
//{
//filled = FALSE;
//}
UpdateData(FALSE);
}
I would create a control variable for the progress control and the check button. Then, do:
void Cgui1Dlg::OnBnClickedsetkill()
{
if(c_Check.GetCheck()==BST_CHECKED)
{
c_Progress.SetPos(100);
}
else
{
c_Progress.SetPos(0);
}
}