I am trying to programmatically pass the content of a QLineEdit into rows of a QTableView using a QPushButton. I was wondering if there is anyone who can provide some guidance on how to do that.
Basically this is the initial situation:
and this is what I am trying to achieve using the QPushButton "Send To TableView" in a dynamical way, which mean that every time I change image and its related content shown inside the two QLineEdit I hit "Send To TableView" and the content is saved as shown below:
Every time I change image I repeat the process.
QSQLITE is the databse that is handling all the SQL for the QTableView. It is structured using this code from my previous question.
How to easily achieve that?
Thanks for shedding light on this issue.
I found out about this post that a very quick and easy answer is the following:
mainwindow.h
private slots:
void on_sendBtn_clicked();
void addData();
On the constructor put:
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
model = new QStandardItemModel();
ui->tableView->setModel(model);
}
Create the function that will be passed to the QPushButton
void MainWindow::on_sendBtn_clicked()
{
addData();
}
void MainWindow::addData()
{
QStandardItem *pathAItem = new QStandardItem(ui->pathLineEdit_A->text());
QStandardItem *pathBItem = new QStandardItem(ui->pathLineEdit_B->text());
QList<QStandardItem*> row;
row << pathAItem << pathBItem;
model->appendRow(row);
}
Hope this will be helpful should anyone needs
Related
I have 1 QListWidget and 1 QStackedWidget. The QstackedWidget has three different widgets to be shown after selecting the entriesd on the QListWidget.
The problem: as I select the first choice nothing happens and nothing happens if I select the second choice, but when I select the last choice I see the widget on the QStackedWidget. This widget does not appartain to the third widget but it appartain to the first widget.
Signals of [QListWidget::currentRowChanged(C++ - QListWidget select first item) does not seem to be triggered correctly. Why is that happening? Basically seems to be triggered only the last choice instead all the others.
Below the snippet of code:
1 solution: works partially because out of three choices I can only see the last QWidget showing on the QStackedWidget:
OptionsDialog::OptionsDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::OptionsDialog)
{
ui->setupUi(this);
mVesPos = new VesselPosSystemWidget;
mSonar = new SonarForm;
mOutput = new OutputForm;
ui->stackedWidget->addWidget(mVesPos);
ui->stackedWidget->addWidget(mSonar);
ui->stackedWidget->addWidget(mOutput);
ui->horizontalLayout->addWidget(ui->stackedWidget);
setLayout(ui->horizontalLayout);
QObject::connect(ui->listWidget, &QListWidget::currentRowChanged,
ui->stackedWidget, &QStackedWidget::setCurrentIndex);
}
OptionsDialog::~OptionsDialog()
{
delete ui;
}
2 solution: works partially because out of three choices I can only see the last QWidget showing on the QStackedWidget. This solution was taken from official documentation of QStackedWidget:
OptionsDialog::OptionsDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::OptionsDialog)
{
ui->setupUi(this);
mVesPos = new VesselPosSystemWidget;
mSonar = new SonarForm;
mOutput = new OutputForm;
ui->stackedWidget->addWidget(mVesPos);
ui->stackedWidget->addWidget(mSonar);
ui->stackedWidget->addWidget(mOutput);
ui->horizontalLayout->addWidget(ui->stackedWidget);
setLayout(ui->horizontalLayout);
connect(ui->listWidget, QOverload<int>::of(&QListWidget::currentRowChanged),
ui->stackedWidget, &QStackedWidget::setCurrentIndex);
}
OptionsDialog::~OptionsDialog()
{
delete ui;
}
3 solution: same exact effect, only the third QWidget is shown:
OptionsDialog::OptionsDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::OptionsDialog)
{
ui->setupUi(this);
mVesPos = new VesselPosSystemWidget;
mSonar = new SonarForm;
mOutput = new OutputForm;
ui->stackedWidget->addWidget(mVesPos);
ui->stackedWidget->addWidget(mSonar);
ui->stackedWidget->addWidget(mOutput);
ui->horizontalLayout->addWidget(ui->stackedWidget);
setLayout(ui->horizontalLayout);
connect(ui->listWidget, &QListWidget::currentRowChanged,
[=](int index) { on_listWidget_currentRowChanged(index); });
}
OptionsDialog::~OptionsDialog()
{
delete ui;
}
void OptionsDialog::on_listWidget_currentRowChanged(int currentRow)
{
ui->stackedWidget->setCurrentIndex(currentRow);
}
I don't know what else to try to have the .ui forms switch after selcting the item in the QListWidget. Is there something I am missing? I tried all possible connect combinations but despite that I can only show the third choice.
I hope this could be useful for other users. I found a solution to this question. It was not easy and it required reading in depth the official documentation. Basically what was happening was that as I tried to select the proper QWidget on the QlistWidget, the selection was erroneously going to the incorrect form. I tried to
qDebug() << ui->stackedWidget->addWidget(mSonar);
qDebug() << ui->stackedWidget->addWidget(mOutput);
And was obtaining index 3,4,5. Which explains why I was only seeing the last index.
Now after long and in-depth reading of the documentation I found out about QStackedWidget::insertWidget relationships with all possible QWidget you want to link to the stack. It basically linking all the views to the form under the precise condition that what you are passing are QWidgets. So for example if you would like to link a QDialog to the QStackedWidget this is not allowed, because QStackedWidgets inherits QWidgets.
Therefore the solution was to insert the correct widget right from the beginning passing the proper index manually (in my case).
Code solution:
OptionsDialog::OptionsDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::OptionsDialog)
{
ui->setupUi(this);
mVesPos = new VesselPosSystemWidget;
mSonar = new SonarForm;
mOutput = new OutputForm;
ui->stackedWidget->insertWidget(0, mVesPos);
ui->stackedWidget->insertWidget(1, mSonar);
ui->stackedWidget->insertWidget(2, mOutput);
// This is how to link the choice according to the latest signals notation
connect(ui->listWidget, &QListWidget::currentRowChanged,
ui->stackedWidget, &QStackedWidget::setCurrentIndex);
}
The function can be found here and you can actually see, if you read carefully how the inheritance works. So again int QStackedWidget::insertWidget(int index, QWidget *widget) from official documentation solved the problem. I hope this could solve the problem for other users. :)
I am building a small interface where I subclassed RViz which is a visualizer from ROS. According to the official documentation it is possible to re-use and re-implement some of the functions present in this tool. What I am trying to do is creating two different QPushButton that will chnage the view of the renderer implemented.
I have some problems with the SIGNAL ans SLOT for my two buttons, in fact as I click them, the view doesn't change.
Now RViz has a specific function called getNumViews() that allows the user to set the number of views. In my case I have two views only related to the two QPushButton I am implementing.
As I run the application program I receive the following error QObject::connect: No such slot MyViz::switchToView() and thought that all the passages to correctly set the SIGNALS and SLOT were correctly according to the official documentation. Also for completeness I am using C++11 and from researching more I found that the old version of the SIGNAL and SLOT, which is the one I am using is supposed to be still valid.
Below the code related to the SIGNAL and SLOT that I am running:
myviz.h
public Q_SLOTS:
void switchToView(QString view);
private:
rviz::ViewManager *view_man;
myviz.cpp
MyViz::MyViz(QWidget *parent) : QWidget(parent)
{
// operation in the constructor
QPushButton *topViewBtn = new QPushButton("Top View");
QPushButton *sideViewBtn = new QPushButton("Side View");
connect(topViewBtn, SIGNAL(clicked()), this, SLOT(switchToView(QString("Top View"))));
connect(sideViewBtn, SIGNAL(clicked()), this, SLOT(switchToView(QString("Side View"))));
}
here is where I set the 2 views possibilities related to the two QPushButtons
void MyViz::switchToView(QString view)
{
view_man = manager->getViewManager();
for(int i = 0; i<view_man->getNumViews(); i++)
{
if(view_man->getViewAt(i)->getName() == view)
view_man->setCurrentFrom(view_man->getViewAt(i));
return;
std::cout<<"Did not find view named %s"<<std::endl;
}
}
Thank you for pointing in the right direction for solving this issue.
You cannot pass arguments in the connect function using the old syntax. Also the number and type of arguments need to match, so you can only connect clicked to functions without arguments. If you want to use the old syntax, you need to define 2 slots
public Q_SLOTS:
void switchToTopView();
void switchToSideView();
which you can then connect via:
connect(topViewBtn, SIGNAL(clicked()), this, SLOT(switchToTopView()));
connect(sideViewBtn, SIGNAL(clicked()), this, SLOT(switchToSideView()));
edit:
The correct syntax for new connect method is:
connect( topViewBtn, &QPushButton::clicked, this, &MyViz::switchToTopView);
The advantage of this method is that you can also bind to lambdas, which indirectly lets you set parameters during connect, so you could write
connect( topViewBtn, &QPushButton::clicked, [this](){
switchToView( QString("Top View") );
});
I using the wxFormbuilder to mimic a QT GUI design, but I always can not success to make a ideal result.
The question is related the alignment/layout. Can anyone give me a hand?
Because I can not attach files here, so I uploaded the wxFormbuilder project file and a qt-gui screenspot .png file to the links below.
If anyone has time, plz give me a guide.
The wxFrombuild project file and the qt_gui .png files are here. http://www.2shared.com/file/62BJYq2l/help_dlg.html http://www.2shared.com/photo/uWl3XmRl/qt_GUI.html
Your design is fairly complicated. I don't use wxFormbuilder, I like to set up my form manually, by "hard coding" the layout.
So before I explain how I would do it, here's a few advice:
I would put the ok/cancel/help bar somewhere else (in a separate wxPanel, and put them together in the dialog at the end)
I would move the test connect button on the ok/cancel/help bar.
The test connect button is in an awful place at the moment in term of setting the layout
(optionally) I would split the form between name/host/database and username/password since they represent some sub unit you can reuse somewhere else
Now here is how I would build the form. I let you implement the getValue and setValue.
Also you'll need to do something similar for the tool bar (using a wxBoxSizer) and put them together (using a wxBoxSizer again).
Also if you may want to use a wxStaticBox
class ConnectionEditor
: wxPanel
{
public:
ConnectionEditor(wxWindow* parent);
//
void getValue(ConnectionSettings&);
void setValue(ConnectionSettings const&);
private:
wxTextCtrl* name_;
wxTextCtrl* host_;
wxTextCtrl* database_;
wxTextCtrl* username_;
wxTextCtrl* password_;
wxCheckBox* save_password_;
};
wxTextCtrl* CreateTextControl(wxWindow* parent)
{
return new wxTextCtrl(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(100, 20));
}
wxTextCtrl* CreateStaticText(wxWindow* parent, std::string const& text)
{
return new wxStaticText(parent, wxID_ANY, text.c_str());
}
ConnectionEditor::ConnectionEditor(wxWindow* parent)
: wxPanel(parent, wxID_ANY)
{
this->name_ = CreateTextControl(this);
this->host_ = CreateTextControl(this);
this->database_ = CreateTextControl(this);
this->username_ = CreateTextControl(this);
this->password_ = CreateTextControl(this);
this->save_password_ = new wxCheckBox(this, wxID_ANY, "on");
//
wxFlexGridSizer* sizer = new wxFlexGridSizer(6, 2, 5, ,5); // 6 rows, 2 cols, 5 spacing in between
//
sizer->Add(CreateStaticText(this, "Name"));
sizer->Add(this->name_);
sizer->Add(CreateStaticText(this, "Host"));
sizer->Add(this->host_);
sizer->Add(CreateStaticText(this, "Database"));
sizer->Add(this->database_);
sizer->Add(CreateStaticText(this, "Username"));
sizer->Add(this->username_);
sizer->Add(CreateStaticText(this, "Password"));
sizer->Add(this->password_);
sizer->Add(CreateStaticText(this, "Save Password"));
sizer->Add(this->save_password_);
//
this->SetSizerAndFit(sizer);
}
I think the title or the question is clear enough. I saw something about the EventSink, but I found it difficult to use. Any hint?
The Visio Primary Interop Assembly exposes these events as C# events therefore you can simply hook the event with a delegate.
See this simple example:
namespace VisioEventsExample
{
using System;
using Microsoft.Office.Interop.Visio;
class Program
{
public static void Main(string[] args)
{
Application app = new Application();
Document doc = app.Documents.Add("");
Page page = doc.Pages[1];
// Setup event handles for the events you are intrested in.
// Shape deleted is easy.
page.BeforeShapeDelete +=
new EPage_BeforeShapeDeleteEventHandler(onBeforeShapeDelete);
// To find out if a shape has moved hook the cell changed event
// and then check to see if PinX or PinY changed.
page.CellChanged +=
new EPage_CellChangedEventHandler(onCellChanged);
// In C# 4 for you can simply do this:
//
// page.BeforeShapeDelete += onBeforeShapeDelete;
// page.CellChanged += onCellChanged;
// Now wait for the events.
Console.WriteLine("Wait for events. Press any key to stop.");
Console.ReadKey();
}
// This will be called when a shape sheet cell for a
// shape on the page is changed. To know if the shape
// was moved see of the pin was changed. This will
// fire twice if the shape is moved horizontally and
// vertically.
private static void onCellChanged(Cell cell)
{
if (cell.Name == "PinX" || cell.Name == "PinY")
{
Console.WriteLine(
string.Format("Shape {0} moved", cell.Shape.Name));
}
}
// This will be called when a shape is deleted from the page.
private static void onBeforeShapeDelete(Shape shape)
{
Console.WriteLine(string.Format("Shape deleted {0}", shape.Name));
}
}
}
If you haven't already downloaded the Visio SDK you should do so. Recent versions of the SDK it contains many useful examples include one called "Shape Add\Delete Event". If you have the 2010 version can browse the examples by going to Start Menu\Programs\Microsoft Office 2010 Developer Resources\Microsoft Visio 2010 SDK\Microsoft Visio Code Samples Library.
I believe that you have to implement EvenSink to get access to "ShapesDeleted", i.e.
(short)Microsoft.Office.Interop.Visio.VisEventCodes.visEvtCodeShapeDelete
the code above will help you if you are looking for the event "BeforeShapeDelete" not the "after"ShapeDelete ;)
I wrote a wxPython program that I am translating to wxWidgets. The program has a scrolled window that displays an image. Following Rappin, wxPython In Action (Listing 12.1), I used a StaticBitmap within a panel. While surfing the latest wxWidgets documentation, I found a dire warning that wxStaticBitmap should only be used for very small images. It says, "... you should use your own control if you want to display larger images portably." Okay. Show me. I don't have my "own control."
Was Rappin wrong, or is the documentation out of date?
The question - a newbie one, no doubt - is what is the right way to do a simple image-view window in wxWidgets? A drop-in replacement for wxStaticBitmap would be nice. I looked into the "image" program in the wxWidgets "samples" directory. It's as long a War and Peace. Surely there must be a canned class or a simple recipe.
Don't let the size of the "image" sample fool you, only a few lines of code are necessary to do what you want.
Search for the MyImageFrame class in the image.cpp file, it is nothing more than a class with a private bitmap field, a custom constructor to set the bitmap and the window client size, and an event handler for EVT_PAINT:
void OnPaint(wxPaintEvent& WXUNUSED(event))
{
wxPaintDC dc( this );
dc.DrawBitmap( m_bitmap, 0, 0, true /* use mask */ );
}
Since you don't want a frame class here's your recipe: You create a simple descendant of wxWindow that has a similar constructor, paint handler and duplicates the methods of wxStaticBitmap that you use in your code. Maybe simply one method to set a new bitmap and resize the control to the new bitmap dimensions.
// A scrolled window for showing an image.
class PictureFrame: public wxScrolledWindow
{
public:
PictureFrame()
: wxScrolledWindow()
, bitmap(0,0)
{;}
void Create(wxWindow *parent, wxWindowID id = -1)
{
wxScrolledWindow::Create(parent, id);
}
void LoadImage(wxImage &image) {
bitmap = wxBitmap(image);
SetVirtualSize(bitmap.GetWidth(), bitmap.GetHeight());
wxClientDC dc(this);
PrepareDC(dc);
dc.DrawBitmap(bitmap, 0, 0);
}
protected:
wxBitmap bitmap;
void OnMouse(wxMouseEvent &event) {
int xx,yy;
CalcUnscrolledPosition(event.GetX(), event.GetY(), &xx, &yy);
event.m_x = xx; event.m_y = yy;
event.ResumePropagation(1); // Pass along mouse events (e.g. to parent)
event.Skip();
}
void OnPaint(wxPaintEvent &event) {
wxPaintDC dc(this);
PrepareDC(dc);
dc.DrawBitmap(bitmap, 0,0, true);
}
private:
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(PictureFrame,wxScrolledWindow)
EVT_PAINT(PictureFrame::OnPaint)
EVT_MOUSE_EVENTS(PictureFrame::OnMouse)
END_EVENT_TABLE()