7

在使用 JUCE 中的可视 WYSISWYG 编辑器制作单页应用程序后,我在弄清楚如何调用新窗口(在主 GUI 窗口之外)时遇到了一些麻烦。我制作了一个测试应用程序,它只有一个使用可视化编辑器创建的最小主 GUI。它有一个按钮“制作新窗口”。我的目标是能够单击该按钮并弹出一个新窗口,并且这个新窗口是 JUCE“GUI 组件”(AKA,图形/可视 GUI 编辑器文件)。现在,我实际上已经实现了这一点,但是,它会抛出错误和断言,因此获得一个非常简单的分步教程会很棒。

我研究了 Projucer 自动创建的 main.cpp 文件,以了解它们是如何创建窗口的。这就是我所做的。

1) 在我的项目中,我添加了一个新的 GUI 组件(它变成了一个类)并将其命名为“InvokedWindow”。2) 在我的主 GUI 组件类头中,我添加了一个 InvokedWindow 类型的新范围指针:ScopedPointer<InvokedWindow> invokedWindow; 3) 我在主 GUI 编辑器中创建了一个名为“Make New Window”的新按钮,并将其添加到处理程序代码中: newWindowPtr = new InvokedWindow;以便任何时候按下按钮,就会创建一个 InvokedWindow 类型的新对象。4) 在 InvokedWindow 类的构造函数中,在自动生成的代码之上,我添加了:

setUsingNativeTitleBar (true);
setCentrePosition(400, 400);
setVisible (true);
setResizable(false, false);

这是我从 JUCE 应用程序的主文件中得到的。

我还在这个新窗口中添加了一个滑块,只是为了向它添加功能。

5)我添加了一个重载函数让我关闭窗口:

void InvokedWindow::closeButtonPressed()
{
    delete this;
}

所以,现在当我运行应用程序并单击 make new window 按钮时,会弹出一个新窗口,但我得到一个断言:

/* Agh! You shouldn't add components directly to a ResizableWindow - this class
   manages its child components automatically, and if you add your own it'll cause
   trouble. Instead, use setContentComponent() to give it a component which
   will be automatically resized and kept in the right place - then you can add
   subcomponents to the content comp. See the notes for the ResizableWindow class
   for more info.

   If you really know what you're doing and want to avoid this assertion, just call
   Component::addAndMakeVisible directly.
*/

此外,我可以关闭一次窗口并点击主 GUI 中的按钮以创建另一个 newWindow 实例,但再次关闭它会导致错误:

template <typename ObjectType>
struct ContainerDeletePolicy
{
    static void destroy (ObjectType* object)
    {
        // If the line below triggers a compiler error, it means that you are using
        // an incomplete type for ObjectType (for example, a type that is declared
        // but not defined). This is a problem because then the following delete is
        // undefined behaviour. The purpose of the sizeof is to capture this situation.
        // If this was caused by a ScopedPointer to a forward-declared type, move the
        // implementation of all methods trying to use the ScopedPointer (e.g. the destructor
        // of the class owning it) into cpp files where they can see to the definition
        // of ObjectType. This should fix the error.
        ignoreUnused (sizeof (ObjectType));

        delete object;
    }
};

这一切都让我有点过头了。我认为能够通过一个按钮创建一个新窗口并不会太糟糕。我可以使用图形 GUI 编辑器编辑一个新窗口,但通过我尝试过,我无法完全靠自己解决所有问题。任何人都可以发布一步一步的指南来正确地做到这一点吗?我确实在 JUCE 论坛上发布了这个,但由于我缺乏 GUI 编程,我无法理解发布的解决方案(我自己的错),所以我希望得到一个非常简单的指南。将不胜感激。谢谢你。

4

1 回答 1

6

我想到了。我需要创建:

  1. 一个新的 GUI 组件(记住,这是 JUCE 中的可视化编辑器)
  2. 一个类(我称它为 BasicWindow,基于 JUCE 演示代码),它充当一个 shell 来运行这个新窗口并保存 GUI 组件。
  3. 一个 JUCE SafePointer,每当单击按钮时都会创建一个 BasicWindow 类型的新对象,并将属性设置为该窗口。

这是我的代码:

参考第 3 行)在按钮的处理程序部分中创建新窗口:

basicWindow = new BasicWindow("Information", Colours::grey, DocumentWindow::allButtons);

basicWindow->setUsingNativeTitleBar(true);
basicWindow->setContentOwned(new InformationComponent(), true);// InformationComponent is my GUI editor component (the visual editor of JUCE)

basicWindow->centreWithSize(basicWindow->getWidth(), basicWindow->getHeight());
basicWindow->setVisible(true);

参考第 2 行)定义 BasicWindow 是什么的 .cpp 文件:

#include "../JuceLibraryCode/JuceHeader.h"

class BasicWindow : public DocumentWindow
{
private:
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BasicWindow)

public:
    BasicWindow (const String& name, Colour backgroundColour, int buttonsNeeded)
    : DocumentWindow (name, backgroundColour, buttonsNeeded)
    {
    }

    void closeButtonPressed() override
    {
        delete this;
    }
};

并参考第 1 行)制作 GUI 编辑器组件,这很容易做到。您只需在 JUCE 文件管理器中添加一个新文件即可。“添加新的 GUI 组件”,然后直观地添加所有元素和处理程序代码。

我最大的问题是我使用的是 JUCE ScopedPointer,所以在删除对象后,指向它的指针并没有被设置回 NULL。SafePointer 执行此操作。如果需要更多解释,我很乐意提供帮助,因为这对于“在他的腰带下”没有太多 GUI 开发的人来说是可怕的。

于 2017-05-09T06:46:31.333 回答