我正在构建一个gtkmm应用程序。该程序打开一个设置窗口,要求用户指定一些信息,完成完整性检查后,应关闭此窗口,并打开应用程序的窗口。
现在,打开主窗口,隐藏设置窗口完全关闭应用程序。 从设置窗口,我正在做:
MainWindow* main_window = new MainWindow();
main_window->show();
this->hide();
如何获得上述行为?
显然,您可以从Gtk::App
添加和删除窗口。它会做我描述的,它是否意味着我必须将Gtk::App
指针传递给我的窗口?感谢。
答案 0 :(得分:0)
似乎正确的解决方案是将应用程序指针(m_app)传递给窗口,向其添加新窗口,显示该窗口并隐藏当前窗口。从应用程序中删除当前的一个将让run()函数返回:
MainWindow* main_window = new MainWindow(m_app);
m_app->add_window(*main_window);
main_window->show();
this->hide();
m_app->remove_window(*this);
delete->this;
这项工作,但这可能不是正确的做事方式。
答案 1 :(得分:0)
针对您的回答:delete->this
是纯语法错误,即使没有->
,编写delete this
通常也是一种代码味道。除非这样做,否则您所做的事情似乎会奏效,甚至可能不那么直观。
但是,并非总是可以按此顺序进行操作。例如,您可能不知道下一个Window
是什么。也许下一个打开的窗口取决于HTTP响应,可能需要一段时间才能到达。
一般的解决方案是在删除Window
之前先调用Application.hold()
。调用.hold()
会增加GApplication
的使用次数,就像添加窗口一样。当其使用计数为零时,该应用程序退出。说它的生命是由Windows控制的,这只是一种大概的解释的快速方法(显然仅与GtkApplication
相关,而不与基础GApplication
相关)。删除窗口会减少使用次数。
因此,在这种情况下,您现在将使用计数从2改为1-而不是1变为0-因此删除第一个窗口将不再使应用程序退出。然后,在添加第二个窗口之后,不管以后发生多少次,都请调用.release()
来删除额外的使用次数,因此其余窗口现在将再次独占控制应用程序的生存期。
答案 2 :(得分:0)
尽管这个问题已经很老了,但我将展示我的方法,该方法可以帮助其他人完成这项任务。
我使用一个包含所有窗口对象的通用应用程序对象:MainApplication.cpp
MainApplication::MainApplication(int argc, char **argv)
{
// Creating the main application object as first
mainApp = Gtk::Application::create(argc, argv, APPLICATION_ID);
// Create the entry window
createEntryWindow();
}
int MainApplication::run()
{
if (!isRunning) {
// Set the current window to entry window for startup
currentWindow = entryWindow;
return mainApp->run(*entryWindow);
} else {
return -1;
}
}
void MainApplication::createEntryWindow()
{
// Load the entry_window.glade layout with the Gtk::Builder Api
Glib::RefPtr<Gtk::Builder> builder = Gtk::Builder::create_from_file("../layout/entry_window.glade");
// Calls the constructor of my own derived widget class which details are specified inside the builder file
builder->get_widget_derived(WND_ENTRY, entryWindow);
// Set this main application object to the new window
entryWindow->setMainApplicationContext(this);
}
MainApplication.h
static const int WS_ENTRY = 100;
static const int WS_SOMETHING = 200;
class MainApplication {
public:
MainApplication(int argc, char* argv[]);
int run();
void switchCurrentWindow(int specifier);
private:
void createEntryWindow();
private:
Glib::RefPtr<Gtk::Application> mainApp;
Gtk::Window* currentWindow = nullptr;
EntryWindow* entryWindow = nullptr;
bool isRunning = false;
};
将在main()内部创建MainApplication对象,然后将run()称为:main.cpp
int main(int argc, char* argv[])
{
// Create main application object
MainApplication mainApplication(argc, argv);
// Starts the event loop
// No events propagate until this has been called
return mainApplication.run();
}
EntryWindow.cpp看起来像这样(只是一个简单的示例):
EntryWindow::EntryWindow(BaseObjectType* object, const Glib::RefPtr<Gtk::Builder>& refGlade)
: Gtk::Window(object), builder(refGlade)
{
// Set widgets to builder
builder->get_widget(btnName, btn);
// Set on click methods for signal_clicked
btn->signal_clicked().connect(sigc::mem_fun(*this, &EntryWindow::onBtnClicked));
}
void EntryWindow::onBtnClicked()
{
mainApplicationContext->switchCurrentWindow(WS_SOMETHING);
}
void EntryWindow::setMainApplicationContext(MainApplication* mainApplication)
{
this->mainApplicationContext = mainApplication;
}
EntryWindow.h:
class EntryWindow : public Gtk::Window {
public:
EntryWindow(BaseObjectType* object, const Glib::RefPtr<Gtk::Builder>& refGlade);
void setMainApplicationContext(MainApplication* mainApplication);
protected:
void onBtnClicked();
protected:
const Glib::RefPtr<Gtk::Builder> builder;
Gtk::Button* btn;
private:
MainApplication* mainApplicationContext = nullptr;
const Glib::ustring btnName = BTN_NAME;
};
因此,现在单击按钮时,您可以在MainApplication类中使用以下功能切换窗口:
void MainApplication::switchCurrentWindow(int specifier)
{
// Check if the passed specifier exist
int tmpSpecifier = 0;
switch (specifier) {
case WS_ENTRY:
tmpSpecifier = WS_ENTRY;
break;
case WS_SOMETHING:
tmpSpecifier = WS_SOMETHING;
break;
default:
tmpSpecifier = 0;
}
// If the specifier exist
if (tmpSpecifier != 0) {
// Increase the use counter of the main application object
mainApp->hold();
// Hide the current window
currentWindow->hide();
// Remove the current window
mainApp->remove_window(*currentWindow);
} else {
return;
}
switch (tmpSpecifier) {
case WS_ENTRY:
currentWindow = entryWindow;
break;
case WS_SOMETHING:
currentWindow = somethingWindow;
break;
}
// Add the new current window
mainApp->add_window(*currentWindow);
// Show the new window
currentWindow->show();
// Decrease the use counter of the main application object
mainApp->release();
}
摘要:创建一个包含所有窗口的对象。因此,无论何时需要新窗口,都必须在此对象内创建它。该主应用程序对象将由main()调用,并在应用程序准备启动时在其中调用run()。之后,您将处理仅由主应用程序对象显示和隐藏哪个窗口。