wxFilePickerCtrl not actualizing widget after setting path - c++

I've got a problem with wxFilePickerCtrl. I tried to set a path with method SetPath(), and it did not work, the path is setted, because i can get it from GetPath(), but the widget still displays path (None).
Here is my code(simplified to two classes). Do you have any idea how can I does it properly? I tried diffrent wxFilePickerCtrl methods from documentation, but results were the same.
main.hpp:
#ifndef MAIN_HPP
#define MAIN_HPP
#include <wx/wx.h>
#include "panel.hpp"
class MyApp : public wxApp
{
public:
bool OnInit();
private:
Panel* _panel;
};
#endif
main.cpp:
#include "main.hpp"
wxIMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
_panel = new Panel();
_panel->Show(true);
return true;
}
panel.hpp:
#ifndef PANEL_HPP
#define PANEL_HPP
#include <wx/wx.h>
#include <wx/filepicker.h>
class Panel : public wxFrame
{
public:
Panel();
private:
wxFilePickerCtrl* _filePicker;
wxBoxSizer* _sizer;
};
#endif
panel.cpp:
#include "panel.hpp"
Panel::Panel() : wxFrame(NULL, wxID_ANY, "MyApp", wxDefaultPosition, wxSize(850, 450))
{
_sizer = new wxBoxSizer(wxVERTICAL);
_filePicker = new wxFilePickerCtrl(this, wxID_ANY, "filePicker");
sizer->Add(_filePicker, 2, wxALIGN_CENTER, 2);
//file does not matter so in examplie I tried to set to main.cpp
_filePicker->SetPath("/some_path/main.cpp");
this->SetSizer(_sizer);
this->Centre();
}

This is a GTK limitation which only shows the name of existing files in this control (so this should work if your /some_path/main.cpp actually exists). I don't see any way to make GtkFileChooserButton show the file name if it doesn't exist, so I don't think this can be fixed, unfortunately.
Generally speaking, this control is really supposed to be used for loading existing files in GTK.

If you want to set it to a file, then you have to use SetFilename
wxFileName fn = "C:/src/wxWidgets.dev/samples/widgets/native.cpp";
filePicker->SetFileName(fn);

Related

QLabel isn't displayed if not a member

I have a class which displays QLabel with some text in QGridLayout. When QLabel is a class member, everything is ok, but when it is not, it isn't displayed in grid.
QLabel is not a member and is created in the constructor.
class Account : public QWidget
{
private:
//QLabel lab;
QGridLayout * grid;
public:
Account(QWidget * parent=0);
public slots:
void spend(int);
void update();
};
.cpp
#include <QLabel>
#include <QLineEdit>
#include <QTextStream>
#include <QFileInfo>
#include <vector>
#include <QGridLayout>
#include <iostream>
Account::Account(QWidget * parent) : QWidget(parent)
{
grid=new QGridLayout(this);
QLabel lab;
lab.setText("RFD");
grid->addWidget(&lab,0,0); //is not displayed
}
QLabel is a member:
class Account : public QWidget
{
private:
QLabel lab;
QGridLayout * grid;
public:
Account(QWidget * parent=0);
public slots:
void spend(int);
void update();
};
.cpp
#include <QLabel>
#include <QLineEdit>
#include <QTextStream>
#include <QFileInfo>
#include <vector>
#include <QGridLayout>
#include <iostream>
Account::Account(QWidget * parent) : QWidget(parent)
{
grid=new QGridLayout(this);
lab.setText("RFD");
grid->addWidget(&lab,0,0); //is displayed
}
WHy is it so?
Because when you declare QLabel in your constructor it is only a local variable, therefore it falls out-of-scope at the end of the function (see my comments below):
{
grid=new QGridLayout(this);
QLabel lab; // created here
lab.setText("RFD");
grid->addWidget(&lab,0,0); //is not displayed
} // destroyed here as the variable is out of scope
note
If you want to create it in your constructor then make it a pointer and new it - you will still need to keep track of this pointer, either as a member variable or pass the pointer to some other function / class to take care of it... (i.e. to delete it when you are finished with it...
Further - addWidget() takes a pointer, so it might handle the destruction of it itself - so you could probably do:
{
grid=new QGridLayout(this);
QLabel *pLab = new QLabel(this);
lab.setText("RFD");
grid->addWidget(pLab,0,0); //is not displayed
}
QLabel lab; is a local variable that lives until the end of the function and then gets automatically destroyed, so the label you want displayed doesn't actually exist anymore when you want to display it.
Furthermore Qt has a broken unconventional memory model that requires you to new up the QLabel and then pass an owning raw pointer to the function which Qt will automatically delete later when the parent gets removed. If you delete it manually you get a double delete (one from you and one from Qt) which usually results in a crash. Manually deleteing an object will automatically detach it from the parent, so you don't get a double delete.
The way Qt wants you to do it is
QLabel *lab = new QLabel;
lab->setText("RFD");
grid->addWidget(lab,0,0);
While this looks like a memory leak, it isn't, due to Qt's memory model.

How to insert items dynamically in scroll area and loading the scroll bar in Qt?

Before we start things, this could be a possible duplicate of Qt Scroll Area does not add in scroll bars, however the answer provided by the user and which seemed to work for the OP, does not work for me. I fear it may have to do with versions, perhaps? Or am I missing something? (it is possible!)
Alright, for those who know Qt, I am a beginner and I have what seem to be a pretty silly problem, but is giving me a lot of headaches:
I want to press a push button and add items to a container, then it is supposed to be possible to scroll it down. As simple as that.
So I thought that perhaps setting a layout to scrollArea would do the job. It indeed adds my items as I wanted, but it doesn't load the scrollBar. I have checked the ScrollPolicy already, but nothing satisfied my issue. It is like the GVBoxLayout doesn't increase size and doesn`t let the scroll area to scroll.
Does anybody have a clue on how to fix it?
Code below:
saleWindow.h
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QListWidget>
#include<QString>
namespace Ui {
class SaleWindow;
}
class SaleWindow : public QMainWindow
{
Q_OBJECT
public:
explicit SaleWindow(QWidget *parent = 0);
~SaleWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::SaleWindow *ui;
QVBoxLayout *gBoxLayout;
QMap<QString, QListWidget *> m_mappings;
};
#endif // SALEWINDOW_H
saleWindow.cpp
#include "salewindow.h"
#include "ui_salewindow.h"
#include <iostream>
#include <QGroupBox>
#include <QLabel>
//#include <QtSql/QSqlDatabase>
//#include <QtSql>
#include <QtWidgets/QPushButton>
SaleWindow::SaleWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::SaleWindow),
gBoxLayout(new QVBoxLayout())
{
ui->setupUi(this);
// Adding layout to scrollbar
{
ui->scrollArea_sales->setWidgetResizable(true);
ui->scrollArea_sales->setLayout(gBoxLayout);
QWidget *central = new QWidget;
ui->scrollArea_sales->setWidget(central);
}
}
SaleWindow::~SaleWindow()
{
delete ui;
delete gBoxLayout;
}
void SaleWindow::on_pushButton_clicked()
{
QGroupBox *sale = new QGroupBox();
sale->setTitle("minha venda");
gBoxLayout->addWidget(sale);
ui->scrollArea_sales->setLayout(gBoxLayout);
}
If you are using a QScrollArea for the scrollArea_sales object from the ui editor, you can see in the object inspector(qtdesigner) a default widget in the QScrollArea, so you not need to add this. Try this code:
// Adding layout to scrollbar(on the contrctor, replace yor scope by)
{
ui->scrollArea_sales->widget()->setLayout(gBoxLayout);
}
void MainWindow::on_pushButton_clicked() {// on the slot replace all by:
QGroupBox *sale = new QGroupBox();
sale->setTitle("minha venda");
ui->scrollArea_sales->widget()->layout()->addWidget(sale);
}

Custom Slot from qt4 design generated h file

Hi Im try to make a custom slot with the h file that qt4 designer generated
I see how the standard slot is made but i would like to, "once past learning this step" have run terminal commands and have it output in the text box so im tryin to replace the past() slot with one i can right commands in
Here is the h file file that works great but.... the above problem'' trying to understand the flow.. 2nd day so any pointers are awsome. so here it is i will comment where i think i should be working.. but have had no success all day lol.
#ifndef SWEETGUIFORMQ19488_H
#define SWEETGUIFORMQ19488_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QHeaderView>
#include <QtGui/QTextEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QWidget>
QT_BEGIN_NAMESPACE
class Ui_SweetGuiForm
{
public:
QVBoxLayout *verticalLayout_2;
QVBoxLayout *verticalLayout;
QTextEdit *textEdit;
QDialogButtonBox *buttonBox;
void setupUi(QWidget *SweetGuiForm)
{
if (SweetGuiForm->objectName().isEmpty())
SweetGuiForm->setObjectName(QString::fromUtf8("SweetGuiForm"));
SweetGuiForm->resize(511, 275);
verticalLayout_2 = new QVBoxLayout(SweetGuiForm);
verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
verticalLayout = new QVBoxLayout();
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
textEdit = new QTextEdit(SweetGuiForm);
textEdit->setObjectName(QString::fromUtf8("textEdit"));
verticalLayout->addWidget(textEdit);
buttonBox = new QDialogButtonBox(SweetGuiForm);
buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
verticalLayout->addWidget(buttonBox);
verticalLayout_2->addLayout(verticalLayout);
QWidget::setTabOrder(textEdit, buttonBox);
retranslateUi(SweetGuiForm);
QObject::connect(buttonBox, SIGNAL(rejected()), SweetGuiForm, SLOT(close()));
ok here i guess i could replace the paste() with on_buttonBox_accepted(), please correct me i really am still quessing at this point but where do i right the function? do i do the in a file called sweetguiform.cpp ? this is where im lost.. help..
QObject::connect(buttonBox, SIGNAL(accepted()), textEdit, SLOT(paste()));
QMetaObject::connectSlotsByName(SweetGuiForm);
} // setupUi
void retranslateUi(QWidget *SweetGuiForm)
{
SweetGuiForm->setWindowTitle(QApplication::translate("SweetGuiForm", "Form", 0, QApplication::UnicodeUTF8));
} // retranslateUi
};
namespace Ui {
class SweetGuiForm: public Ui_SweetGuiForm {};
} // namespace Ui
QT_END_NAMESPACE
#endif // SWEETGUIFORMQ19488_H
Is this the way to do things when brand new?
I think you shouldn't be editing the header file that Qt generates for you. Instead, you should write your own header/implementation file that includes this auto-generated header and sets up the signal-slot connections there. For example:
#include "ui_SweetGuiForm.h"
class SweetGuiForm : public QWidget
{
public:
SweetGuiForm( ): ui( new Ui::SweetGuiForm )
{
ui->setupUi( this );
}
public slots:
void on_buttonBox_accepted( )
{
// your code here
}
protected:
Ui::SweetGuiForm* ui;
};
Qt will find the on_buttonBox_accepted method and set up the signal-slot connection for you, so you don't have to call QObject::connect.

Filling window with a wxWebView

I would like to fill an application window created with wxWidgets with a wxWebView. After reviewing the wxWebView sample, there the author created a wxFrame which then contained a wxBoxSizer and a wxWebView was added directly to that. However I would like my application to use a wxSingleChoiceDialog, so as far as I can tell, that means I need to include something like a wxPanel to use as the dialog's parent (the first argument to the constructor is the 'parent' of type wxWindow). So in my application I put a wxPanel in the wxFrame and then set the wxBoxSizer of the wxPanel to include the wxWebView. Unfortunately now the wxWebView no longer fits the full application window and I'm not sure why. Here is a simplified example of the application I'm trying to create.
main.h
#ifndef MAIN_H
#define MAIN_H
#include <wx/wx.h>
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
DECLARE_APP(MyApp)
#endif
main.cpp
#include "main.h"
#include "mainframe.h"
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
MainFrame *mainFrame = new MainFrame(wxT("Content Creator"));
mainFrame->Show(true);
return true;
}
mainframe.h
#ifndef MAINFRAME_H
#define MAINFRAME_H
#include <wx/wx.h>
#include <wx/webview.h>
class MainFrame : public wxFrame
{
public:
wxPanel *panel;
wxBoxSizer *topsizer;
wxMenuBar *menubar;
wxMenu *file;
wxWebView *webView;
wxString editorURL;
MainFrame(const wxString& title);
void initMenu();
void initEditor();
};
#endif
mainframe.cpp
#include "mainframe.h"
MainFrame::MainFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(800,600))
{
panel = new wxPanel(this, -1);
topsizer = new wxBoxSizer(wxVERTICAL);
panel->SetSizer(topsizer);
initMenu();
initEditor();
}
void MainFrame::initMenu()
{
menubar = new wxMenuBar;
file = new wxMenu;
//file->Append(wxID_EXIT, wxT("Quit"));
menubar->Append(file, wxT("File"));
SetMenuBar(menubar);
}
void MainFrame::initEditor()
{
editorURL = "file:///C:/Users/kenwood/Desktop/MarkCreator2/ckeditor/samples/editor.html";
webView = wxWebView::New(panel, wxID_ANY, editorURL);
topsizer->Add(webView, 1, wxEXPAND | wxALL, 0);
}
Here is a screenshot of the application this creates: Screenshot
Does anyone know how I might be able to make this wxWebView fill the application window (or at least why it isn't fitting the window because I'm clearly missing something here)? I realize I can create a wxWebView an specify a a size that would be equal to the window size, but then when the user resizes the screen webview is no longer the same size as the application window.
Thanks.
EDIT:
Also, I'm using wxWidgets version 2.9.4
EDIT 2:
It appears that calling initEditor() before initMenu() produces the desired result (but not the other way around). Would anyone know what the reason for this is? I would really like to call initMenu() first if that is possible.
You need to add the webView to the panels sizer. Your question actually doesn't have anything to do with wxWebView but just concerns the layout and I strongly recommend (re)reading the corresponding section of the manual.
For anyone having similar problems, one of the main problems with my code is that I was creating the 'panel' before creating the menubar. By calling initMenu() as the first function call in the constructor I was able to get the webview to display in the full application window --advice provided by the illustrious 'doublemax' of wxWidgets forums. Thanks for everyone's help.

breakpoint inside QComboBox subclass not working

I have subclassed QComboBox to customize it for special needs. The subclass is used to promote QComboBoxes in a ui file from QtDesigner. Everything works except that when I put a break point in a slot, the program does not stop at the breakpoint. I do however know that it is being called from the result it generates. I checked other slots in my program and they work fine with breakpoints. Doing a clean and rebuild all did not fix it. What could be causing this and is there anything I can do about it? The slot in question is the only one in the subclass and is called "do_indexChanged()". You can find the slot on line 37 of the class header below and the signal-slot connection on line 10 of the class source file.
CLASS HEADER:
#ifndef WVQCOMBOBOX_H
#define WVQCOMBOBOX_H
#include <QWidget>
#include <QObject>
#include <QComboBox>
#include <QVariant>
class wvQComboBox : public QComboBox
{
Q_OBJECT
//Q_PROPERTY(bool writeEnable READ writeEnable WRITE setWriteEnable)
public:
explicit wvQComboBox(QWidget *parent = 0);
bool writeEnable() {
return this->property("writeEnable").toBool();
}
void setWriteEnable(const bool & writeEnable){
this->setProperty("writeEnable",writeEnable);
}
bool newValReady() {
return this->property("newValReady").toBool();
}
void setNewValReady(const bool & newValReady){
this->setProperty("newValReady",newValReady);
}
QString getNewVal();
int getNewValIndex();
int oldVal; //comboBox Index before user edit began
private slots:
void do_indexChanged(){
this->setWriteEnable(true);
if(oldVal!=currentIndex()){
this->setNewValReady(true);
oldVal=currentIndex();
}
}
protected:
void focusInEvent ( QFocusEvent * event );
//void focusOutEvent ( QFocusEvent * event );//dont need because of currentIndexChanged(int)
};
#endif // WVQCOMBOBOX_H
#include "wvqcombobox.h"
wvQComboBox::wvQComboBox(QWidget *parent) :
QComboBox(parent)
{
this->setWriteEnable(true);
this->setNewValReady(false);
oldVal=this->currentIndex();
connect(this,SIGNAL(currentIndexChanged(int)),this,SLOT(do_indexChanged()));
}
void wvQComboBox::focusInEvent ( QFocusEvent * event ) {
this->setWriteEnable(false);
oldVal=this->currentIndex();
}
QString wvQComboBox::getNewVal(){
setNewValReady(false);
return this->currentText();
}
int wvQComboBox::getNewValIndex(){
setNewValReady(false);
return this->currentIndex();
}
This is most likely due to the fact that that file was not compilled with debug info, therefore the debugger won't be able to break there. Try linking your app to a debug version of libQtGui*.so/.dylib/.dll
I found the problem. All I needed to do was to put the function definition in the .cpp file.