java 仅 JFrame 可调整高度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3663174/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 02:55:01  来源:igfitidea点击:

JFrame resizable height ONLY

javaswinguser-interfacejframeresizable

提问by brian_d

JFrame.setResizable(true)lets the user resize both the width and height of a window. Does a method exist which allows the user to ONLY resize the height?

JFrame.setResizable(true)允许用户调整窗口的宽度和高度。是否存在允许用户仅调整高度的方法?

Thanks.

谢谢。

Edit:The solutions below do NOT seem to work. On a 360x600 JFrame,

编辑:下面的解决方案似乎不起作用。在 360x600 JFrame 上,

setResizable(true);
pack();
setMaximizedBounds(new java.awt.Rectangle(0, 0, 360, 1200));
setMaximumSize(new java.awt.Dimension(360, 1200));
setMinimumSize(new java.awt.Dimension(360, 600));
setPreferredSize(new java.awt.Dimension(360, 600));
setVisible(true);

Still allows fully stretching the width of the JFrame, and setting setResizable(false)allows nothing to be stretched.

仍然允许完全拉伸 JFrame 的宽度,并且设置setResizable(false)不允许拉伸任何东西。

回答by Haozhun

The code below does the job right.

下面的代码可以正确地完成工作。

addComponentListener(new ComponentAdapter() {

    @Override
    public void componentResized(ComponentEvent e) {
        setSize(new Dimension(preferredWidth, getHeight()));
        super.componentResized(e);
    }

});

回答by Rick Hodgin

If you have experience with JNI, then this is a possible solution.

如果您有使用 JNI 的经验,那么这是一个可能的解决方案。

In Windows and Oracle Hotspot, this code will allow a window to be resized between minimum and maximum dimensions without flickering or causing any of the nasty JFrame-post-resize side-effects. If this code is called once the JFrame is created and made visible, then the code used above in componentResized() to catch resize events can be completely done away with, as Windows has facilities to keep the user from being able to resize above or below the specified min/max sizes.

在 Windows 和 Oracle Hotspot 中,此代码将允许窗口在最小和最大尺寸之间调整大小,而不会闪烁或导致任何讨厌的 JFrame-post-resize 副作用。如果在创建 JFrame 并使其可见后调用此代码,则可以完全取消上面在 componentResized() 中用于捕获调整大小事件的代码,因为 Windows 具有防止用户在上方或下方调整大小的功能指定的最小/最大尺寸。

// Java code:

// Java代码:

static {
    if (System.getProperty("sun.arch.data.model").equals("32"))
    {   // 32-bit JVM
        System.loadLibrary("my32bitdll");
        System.out.println("Running 32-bit JVM");

    } else {
        // 64-bit JVM
        System.loadLibrary("my64bitdll");
        System.out.println("Running 64-bit JVM");
    }
}
// Sets a window to never be resized above or below these minimum widths/heights
public static native int setMinMaxResizeBoundaries(int hwnd, int minWidth, int minHeight, int maxWidth, int maxHeight);

// C++ code (include standard windows.h, winbase.h, etc)

// C++ 代码(包括标准 windows.h、winbase.h 等)

// Global variables defined in DllMain.cpp
// Used for setMinMaxResizeBoundaries()
struct SHwndMinMax
{
    HWND    hwnd;
    int     minWidth;
    int     minHeight;
    int     maxWidth;
    int     maxHeight;
    WNDPROC prefWndProc;
};
SHwndMinMax gsHwndMinMax[2048];
int gsHwndMinMaxCount = 0;
LRESULT CALLBACK MinMaxWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);


// Code added somwhere:
// setMinMaxResizeBoundaries()
// Sets the resize boundary window sizes, so the window will not be resized above/below that size
JNIEXPORT jint JNICALL Java_your_class_here_setMinMaxResizeBoundaries(JNIEnv* env, jclass cls,
    jint hwnd,
    jint minWidth, jint minHeight,
    jint maxWidth, jint maxHeight)
{
    // We create a hook for the window, and intercept the WM_GETMINMAXINFO message occurs, and update the info
    if (IsWindow((HWND)hwnd))
    {   // Let's add it
        if (gsHwndMinMaxCount < 2048)
        {   // We're good
            // Can add code here to check if this option is valid or not--so it can later be "unhooked" by a separate function call
            gsHwndMinMax[gsHwndMinMaxCount].hwnd        = (HWND)hwnd;
            gsHwndMinMax[gsHwndMinMaxCount].minWidth    = minWidth;
            gsHwndMinMax[gsHwndMinMaxCount].minHeight   = minHeight;
            gsHwndMinMax[gsHwndMinMaxCount].maxWidth    = maxWidth;
            gsHwndMinMax[gsHwndMinMaxCount].maxHeight   = maxHeight;
            gsHwndMinMax[gsHwndMinMaxCount].prefWndProc = (WNDPROC)SetWindowLongPtr((HWND)hwnd, GWLP_WNDPROC, (LONG_PTR)&MinMaxWindowProc);
            // Success
            ++gsHwndMinMaxCount;
            return(0);

        } else {
            // Failuire, too many hooks
            return(-2);
        }

    } else {
        // Failure, HWND is not valid
        return(-1);
    }
}

LRESULT CALLBACK MinMaxWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    int i;
    MINMAXINFO* mmi;

    for (i = 0; i < gsHwndMinMaxCount; i++)
    {
        if (hwnd == gsHwndMinMax[i].hwnd)
        {   // This is our man, see if it's our message
            if (msg == WM_GETMINMAXINFO)
            {   // It is
                // When maximized, window is at upper-left
                mmi = (MINMAXINFO*)lParam;
                mmi->ptMaxSize.x        = gsHwndMinMax[i].maxWidth;
                mmi->ptMaxSize.y        = gsHwndMinMax[i].maxHeight;
                mmi->ptMaxPosition.x    = 0;  // Can add code here to properly position the window centered in the screen, etc.
                mmi->ptMaxPosition.y    = 0;  // Same here
                // Set the minimum and maximum tracking size (when the user is resizing, what's the smallest and biggest window they see)
                mmi->ptMinTrackSize.x   = gsHwndMinMax[i].minWidth;
                mmi->ptMinTrackSize.y   = gsHwndMinMax[i].minHeight;
                mmi->ptMaxTrackSize.x   = gsHwndMinMax[i].maxWidth;
                mmi->ptMaxTrackSize.y   = gsHwndMinMax[i].maxHeight;
                return(DefWindowProc(hwnd, msg, wParam, lParam));

            } else {
                // Nope, pass it on
                return(CallWindowProc(gsHwndMinMax[i].prefWndProc, hwnd, msg, wParam, lParam));
            }
        }
    }
    return(0);
}

// The following is code to get the HWND accurately:

// 以下是准确获取HWND的代码:

// Java Code (add to Java code above)

// Java 代码(添加到上面的 Java 代码中)

// Returns the HWND for the specified component, or -1 if does not exist
public static native int getComponentHWND(Component c);

// Code in C++

// C++ 代码

// getComponentHWND()
// Called to return the HWND of the component, if it has one.
JNIEXPORT jint JNICALL Java_your_class_here_getComponentHWND(JNIEnv* env, jclass cls, jobject obj)
{
    HWND hWnd = 0;
    typedef jboolean (JNICALL *PJAWT_GETAWT)(JNIEnv*, JAWT*);
    JAWT awt;
    JAWT_DrawingSurface* ds;
    JAWT_DrawingSurfaceInfo* dsi;
    JAWT_Win32DrawingSurfaceInfo* dsi_win;
    jboolean result;
    jint lock;
    HMODULE _hAWT = 0;

    // Load AWT Library
    if (!_hAWT)
        _hAWT = LoadLibrary(L"jawt.dll");   // for Java 1.4+

    if (!_hAWT)
        _hAWT = LoadLibrary(L"awt.dll");    // for Java 1.3

    if (_hAWT)
    {
        PJAWT_GETAWT JAWT_GetAWT = (PJAWT_GETAWT)GetProcAddress(_hAWT, "JAWT_GetAWT");
        if (JAWT_GetAWT)
        {
            awt.version = JAWT_VERSION_1_4;     // Init here with JAWT_VERSION_1_3 or JAWT_VERSION_1_4
            // Get AWT API Interface
            result = JAWT_GetAWT(env, &awt);
            if (result != JNI_FALSE)
            {
                ds = awt.GetDrawingSurface(env, obj);
                if (ds != NULL)
                {
                    lock = ds->Lock(ds);
                    if ((lock & JAWT_LOCK_ERROR) == 0)
                    {
                        dsi = ds->GetDrawingSurfaceInfo(ds);
                        if (dsi)
                        {
                            dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
                            if (dsi_win)
                                hWnd = dsi_win->hwnd;
                            else
                                hWnd = (HWND) -1;   // Failed to obtain the handle (not running on Windows)

                            ds->FreeDrawingSurfaceInfo(dsi);

                        } else {
                            hWnd = (HWND)-2;    // Failed to get the drawing surface info block
                        }
                        ds->Unlock(ds);

                    } else {
                        hWnd = (HWND)-3;    // Failed to lock the drawing surface to obtain information about it
                    }
                    awt.FreeDrawingSurface(ds);

                } else {
                    hWnd = (HWND)-4;    // Failed to get the drawing surface from the compoment
                }
            } else {
                hWnd = (HWND)-5;    // Failed to obtain a proper result from _JAWT_GetAWT()
            }
        } else {
            hWnd = (HWND)-6;    // Failed to find "_JAWT_GetAWT()" function
        }
    } else {
        hWnd = (HWND)-7;    // Failed to load awt.dll
    }
    return (jint)hWnd;
}

回答by Noel Ang

I do not think there is a method expressly for that purpose. However, you could preset the JFrame's preferred, minimum, and maximum size such that the widths are all equal.

我认为没有明确的方法用于该目的。但是,您可以预设 JFrame 的首选大小、最小大小和最大大小,使宽度都相等。

Dimension dimPreferred = frame.getPreferedSize();
Dimension dimMinimum = frame.getMinimumSize();
Dimension dimMaximum = frame.getMaximumSize();
dimPreferred.setWidth( FIXED_WIDTH );
dimMinimum.setWidth( FIXED_WIDTH );
dimMaximum.setWidth( FIXED_WIDTH );
frame.setPreferredSize( dimPreferred );
frame.setMinimumSize( dimMinimum );
frame.setMaximumSize( dimMaximum );

You will probably want to do this afterframe.pack()and beforeframe.setVisible(true).

您可能希望在之后frame.pack()之前执行此操作frame.setVisible(true)

回答by Tom Hawtin - tackline

I believe most platforms will honour setMaximumSizeand setMinimumSize. There is also setMaximizedBounds.

我相信大多数平台都会尊重setMaximumSizesetMinimumSize。还有setMaximizedBounds

What doesn't work is adding a listener to reset the width. Threading issues makes it look unpleasant. If you have PL&F decorated windows (not supported by the Windows PL&F), then they can be hacked about with.

不起作用的是添加一个监听器来重置宽度。线程问题使它看起来不愉快。如果您有 PL&F 装饰的窗口(Windows PL&F 不支持),那么它们可能会被黑客入侵。

回答by Dheeraj Bhaskar

Instead of setResizable(true)use setResizable(false)Infact setResizable(false) did the trick for me. It even disabled maximization (dimmed the icon)

而不是setResizable(true)使用setResizable(false)Infact setResizable(false) 为我做了诀窍。它甚至禁用了最大化(使图标变暗)

Okay, I should have explained myself better. I wanted to get the resizeable thing working too. That's why I landed on this question. But I finally went with this, thought that would help the OP.

I wanted to do resizable too, but thought if I can't get resizable to work, disabling is better because it won't mess up your content placement. Thought I'd suggest that as a solution.

好吧,我应该更好地解释自己。我也想让可调整大小的东西工作。这就是我登陆这个问题的原因。但我终于同意了,认为这会帮助 OP。

我也想调整大小,但我想如果我不能调整大小来工作,禁用会更好,因为它不会弄乱你的内容位置。以为我会建议将其作为解决方案。

回答by Oleh Toder

To avoid flickering, you can override #setBounds method in your JFrame. Seems like every resize will call it. Something like

为避免闪烁,您可以在 JFrame 中覆盖 #setBounds 方法。似乎每次调整大小都会调用它。就像是

@Override
public void setBounds(int x, int y, int width, int height) {
    if (width == FIXED_WIDTH) {
        super.setBounds(x, y, width, height);
    }
}

did the trick for me.

帮我解决了这个问题。

回答by theoneiam

I am using this code exactly for this purpose and it works (it is actually edited @Hoazhun solutionas his original code will lock both width and height, but in my version you can set height manually yet having width fixed):

我正是为此目的使用此代码并且它有效(它实际上是编辑@Hoazhun 解决方案,因为他的原始代码将锁定宽度和高度,但在我的版本中,您可以手动设置高度但宽度固定):

int defWindowW = 300;
int defWindowH = 600;
JFrame MAIN_WINDOW = new JFrame();

MAIN_WINDOW.addComponentListener(new ComponentAdapter() {

    public void componentResized(ComponentEvent e) {

        int W = Integer.parseInt(e.paramString().split(",")[1].split(" ")[1].split("x")[0].replace(")", ""));
        int H = Integer.parseInt(e.paramString().split(",")[1].split(" ")[1].split("x")[1].replace(")", ""));

        /* FOR FIXED WIDTH - ACTIVE NOW, COMMENT IT OUT FOR DISABLING*/ MAIN_WINDOW.setSize(new Dimension(defWindowW, H));
        
        /* FOR FIXED HEIGHT - UNCOMMENT TO MAKE IT ACTIVE */
        //MAIN_WINDOW.setSize(new Dimension(W, defWindowH));

        super.componentResized(e);
    }
});