I have a custom button that can be right clicked in addition to left clicking. It works like this:
private slots:
void mousePressEvent(QMouseEvent *e) {
if(e->button() == Qt::RightButton) {
std::cout << "kek2";
emit rightClicked();
}
QPushButton::mousePressEvent(e);
}
For some weird reason left click works fine, and right clicks are not processed (judging by lack of kek2 outputs) until I do a left click, upon which all right clicks are processed at once. Why?
I had a look at it and implemented an equivalent Button and changed your code to this:
void QRightClickButton::mousePressEvent(QMouseEvent *e)
{
if(e->button() == Qt::RightButton) {
std::cout << "kek2" << std::endl; //the << std::endl; //made it work good again
emit rightClicked();
} else if(e->button() == Qt::LeftButton) {
//this else if block is just a fast implementation of the leftclick
std::cout << "kek3" << std::endl;
QPushButton::mousePressEvent(e);
}
}
Try it yourself both log messages ("kek2" as well as "kek3") appear instantly.
Without the << std::endl; it is still buggy!
EDIT: I decided to add 2 more ways to do it!
You can also use it without std::endl;
std::cout << message; //prints message
std::cout.flush(); //flushes the output so it will be visible as well
For example you can create your own class or your own function.
Use qDebug(). qDebug automatically flushes the stream so you don't have to write extra code as well as it belongs to Qt self. That means you're not going to mix 2 libraries.
Use it that way:
qDebug() << message;
You should use qDebug() since it ensures that the output is immediately flushed. std::cout doesn't have to. E.g. qDebug() << "kek2". When using Qt, don't use std::cout for debug output, it's not worth it.
mousePressEvent is not a slot.
Related
When I debug the pcl documentation visualization mouse event function code as following shows:
viewer->registerMouseCallback(mouseEventOccurred, (void*)&viewer);
void mouseEventOccurred(const pcl::visualization::MouseEvent &event,void* viewer_void)
{
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer = *static_cast<boost::shared_ptr<pcl::visualization::PCLVisualizer> *> (viewer_void);
if (event.getButton() == pcl::visualization::MouseEvent::LeftButton &&
event.getType() == pcl::visualization::MouseEvent::MouseButtonRelease)
{
std::cout << "Left mouse button released at position (" << event.getX() << ", " << event.getY() << ")" << std::endl;
char str[512];
sprintf(str, "text#%03d", text_id++);
viewer->addText("clicked here", event.getX(), event.getY(), str);
}
}
If I remove the code:
viewer->addText("clicked here", event.getX(), event.getY(), str);
It would work well, or I encountered an error:
I do not know how to solve this problem. Thanks!
After I clicked the Retry, the exception shows as:
Exception
I am creating a simple MP3 player and using the FMOD Core API for managing the audio. I have written a simple program to test the play() function.
I have two functions freeSound() and freeSystem() to free the sound and the system handle respectively. Both are called through the function cleanUp() in the destructor.
I have used gdb to figure out that for some reason, my program gets stuck in the Sound::release() call in freeSound() when the destructor is called.
This problem occurs only when freeSystem() is called before freeSound(). Simply calling the latter first fixes this issue.
I have shared as little code as I thought was possible to show this problem. If more/less is required I will add/remove.
The main() function:
int main()
{
musicPlayer p{"music.mp3"};
std::cout << "load success\n";
p.play();
std::cout << "press enter to quit\n";
std::cin.get();
}
The class declaration (includes only relevant bits):
class musicPlayer
{
private:
FMOD::System *m_system = nullptr;
FMOD::Sound *m_sound = nullptr;
/*Some more functions*/
void cleanUp();
void freeSystem();
void freeSound();
public:
~musicPlayer();
/*Some more functions*/
};
Destructor:
musicPlayer::~musicPlayer()
{
cleanUp();
m_channel = nullptr;
}
cleanUp():
void musicPlayer::cleanUp()
{
freeSystem();
freeSound();
}
freeSound() and freeSystem():
void musicPlayer::freeSystem()
{
if(m_system == nullptr)
return;
FMOD_RESULT result = m_system -> release();
if(result != FMOD_OK){
std::cerr << "freeSystem() Error: " << FMOD_ErrorString(result) << "\n";
return;
}
else
m_system = nullptr;
}
void musicPlayer::freeSound()
{
if(m_sound == nullptr)
return;
FMOD_RESULT result = m_sound -> release();
if(result != FMOD_OK){
std::cerr << "freeSound() Error: " << FMOD_ErrorString(result) << "\n";
return;
}
else
m_sound = nullptr;
}
I expect the audio to stop playing and the program to immediately quit when enter is pressed.
Instead, on pressing enter, the audio stops and the program does not quit.
UPDATE:
Earlier, I wrote:
Blockquote
I have written little test programs where I have called System::release() before Sound::release(). Such programs do not exhibit this issue.
I was wrong. The issue can be reproduced by playing a sound, calling cin.get() and then freeing the resources in the order wrong order.
The FMOD reference FMOD System::close should explain the behaviour:
"Closing renders objects created with this System invalid. Make sure any Sound, ChannelGroup, Geometry and DSP objects are released before calling this.".
System::close is called by System::release so when releasing the system before the components you stumble into problems. As you have found out yourself simply free everything before you release the system.
What is the difference between the output of event.window.windowID and SDL_GetWindowID()?
Why is it that std::cout << m_SDLEvent.window.windowID << std::endl;
outputs 1819558491 in console while std::cout << SDL_GetWindowID(m_SDLWindow) << std::endl; outputs 1 ?
How would I achieve getting the right ID of my SDL_Window* in the method below?
void InputManager::Update()
{
SDL_PollEvent(&m_SDLEvent);
switch (m_SDLEvent.type)
{
case SDL_QUIT:
std::cout << m_SDLEvent.window.windowID << std::endl;
SDL_HideWindow(SDL_GetWindowFromID(m_SDLEvent.window.windowID));
break;
}
}
You're seeing garbage window ID because you access an inactive union field. That's undefined behavior.
You can only access m_SDLEvent.window if m_SDLEvent.type == SDL_WINDOWEVENT.
But if m_SDLEvent.type == SDL_QUIT, you have to use m_SDLEvent.quit structure, which has no field for window id (because SDL_QUIT is not specific to a window, but means that the entire application should be closed).
Okay so HolyBlackCat's answer brought me to the right direction.
Instead of using SDL_QUIT (which is the quit event for the entire app, not one window) I should've checked for SDL_WINDOWEVENT_CLOSE which is an SDL_WINDOWEVENT which can be received by m_SDLEvent.window.event instead of m_SDLEvent.type
So the code now looks like this:
void InputManager::Update()
{
SDL_PollEvent(&m_SDLEvent);
if (m_SDLEvent.type == SDL_WINDOWEVENT)
{
switch (m_SDLEvent.window.event)
{
case SDL_WINDOWEVENT_CLOSE:
std::cout << m_SDLEvent.window.windowID << std::endl;
SDL_HideWindow(SDL_GetWindowFromID(m_SDLEvent.window.windowID));
break;
}
}
}
Now std::cout << m_SDLEvent.window.windowID << std::endl; outputs the correct ID.
I have a folder with many images, I've loaded the filenames into a vector of string and want to display the images in a GTK::Image component like a video, 25 frames (images) per second. But I the component don't re-draw after run the app.
I call the queue_draw(), but nothing change. How I do it?
EDIT:
The main function is like:
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create("org.gtkmm.example");
refBuilder = Gtk::Builder::create();
try{
refBuilder->add_from_file("main_window2.glade");
}
catch(const Glib::FileError& ex){
std::cerr << "FileError: " << ex.what() << std::endl;
return 1;
}
catch(const Glib::MarkupError& ex){
std::cerr << "MarkupError: " << ex.what() << std::endl;
return 1;
}
catch(const Gtk::BuilderError& ex){
std::cerr << "BuilderError: " << ex.what() << std::endl;
return 1;
}
refBuilder->get_widget("main_window", main_window);
cout << "window: " << main_window << endl;
if(main_window)
{
Gtk::ImageMenuItem* newButton = nullptr;
Gtk::ImageMenuItem* openButton = nullptr;
Gtk::ImageMenuItem* saveButton = nullptr;
Gtk::Button* playButton = nullptr;
refBuilder->get_widget("new_button", newButton);
refBuilder->get_widget("open_button", openButton);
refBuilder->get_widget("save_button", saveButton);
refBuilder->get_widget("play_button", playButton);
refBuilder->get_widget("image_container", container);
refBuilder->get_widget("image_component", image_component);
if(playButton)
playButton->signal_clicked().connect(sigc::ptr_fun(on_image_draw));
if(newButton)
newButton->signal_activate().connect( sigc::ptr_fun(on_new_button_activate) );
if(openButton)
openButton->signal_activate().connect( sigc::ptr_fun(on_open_button_activate) );
if(saveButton)
saveButton->signal_activate().connect( sigc::ptr_fun(on_save_button_activate) );
cout << "running main window" << endl;
app->run(*main_window);
}
delete main_window;
And when clicked in playButton, the drawing code is called
static void on_image_draw(){
string path = video.getDirectory();
string aux = path + "/";
cout << "reproduzindo: " << aux << endl;
vector<string> vetor = video.get_imageVector();
cout << "vetor" << endl;
for(auto frame: video.get_imageVector()){
aux += frame;
cout << "frame: " << aux << endl;
image->clear();
image->set(aux);
Glib::RefPtr<Gdk::Pixbuf> pix = image->get_pixbuf();
pix = pix->scale_simple(WIDTH, HEIGHT, Gdk::INTERP_BILINEAR);
image->set(pix);
image->queue_draw();
aux = path+"/";
sleep(1);
}
}
You're not supposed to draw all your frames in the draw signal handler. You basically need to set the image, then call queue_draw. You're doing this right, but then you must let GTK+ do its part of the work. You can't just loop: calling queue_draw puts a draw event in the main loop that GTK+ needs to process to draw your image.
Remember you are single-threaded, so the CPU is like a shovel. When you are in a callback, you get the shovel and do your work. You can't expect GTK+ to process the events you send to it if you don't give it the shovel back.
Here's how you're supposed to architcture this stuff. Please keep in mind that if you need 25fps, this approach is sub-optimal, and you should probably give a look at video libraries like gstreamer.
So when you press play, you're supposed to trigger an event source like a timer or idle handler. That's because you need something to say: I need to isplay a new image. Give a look at g_timeout_add or g_idle_add in the GLib for that (I know only the names for the C api, find the equivalent ones in gtkmm).
Then in the callback associated to that timeout or idle event, you set your image (a single one, no loop), and that's all. Not sure calling queue_draw is even required. It would be if you were drawing by hand in a GtkDrawingArea, but as that's a GtkImage, so by setting a new image you say implicitely that the image has changed and should be redrawn.
I am writing a keyboard tester, so I start a dialog with
keybDialog keyboardTestWindow;
keyboardTestWindow.setWindowTitle("Keyboard test");
keyboardTestWindow.exec();
override the keyPressEvent(QKeyEvent *event) and the test works superb. Now, I needed use of some parameters from parent, so instead I did
keybDialog keyboardTestWindow(m_parent);
keyboardTestWindow.setWindowTitle("Keyboard test");
keyboardTestWindow.exec();
and implemented what I needed. Now I discovered that just by instantiating the class and passing the parent to it, my dialog no longer receives the keyPressEvent. Are these passed to m_parent in some way? How can I avoid this?
EDIT:
The beginning of my keyPressEvent:
void keybDialog::keyPressEvent(QKeyEvent *event)
{
ui->txtBxKeyboardInput->clear();
qDebug() << "Event: " << hex << event->key() << event->nativeVirtualKey() << event->modifiers() << event->nativeModifiers() << event->nativeScanCode();
ui->txtBxKeyboardInput->setText(ui->txtBxKeyboardInput->text()+event->text());
switch(sequenceNumber)
{
case 0: // Left Shift + R
if( (event->key() == Qt::Key_R) && event->modifiers() == Qt::ShiftModifier && event->nativeModifiers() == 0x201)
{
reportSuccessfullKey(sequenceNumber);
}
else
{
ui->lblStatus->setText("WRONG");
}
break;