JFrame可调整大小仅限高度

7

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

谢谢。

编辑:下面的解决方案似乎不起作用。在一个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);

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


你后来找到解决方案了吗? - Haozhun
7个回答

8
下面的代码可以正常运行。
addComponentListener(new ComponentAdapter() {

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

});

谢谢!这行代码可行,因为我主要关心保持最小宽度,所以这段代码非常好用:if (getWidth() < preferredWidth) { setSize(new Dimension(preferredWidth, getHeight())); } - brian_d
@brian_d 我其实也在寻找同样的问题解决方案。很失望地发现你的问题并没有我所需要的答案。不过,无论如何,我在互联网上的其他地方找到了解决方案,并且它起作用了。 - Haozhun
这个功能运行得很好,但它无法防止用户最大化窗口。 - Bao-Long Nguyen-Trong
@DheeB 我们需要固定高度而不是固定大小。 - Haozhun
3
很不幸,当你像这样与布局管理器进行斗争时,会导致 GUI 内部出现难看的持久性闪烁,这对我来说相当严重。 - fragorl
显示剩余2条评论

3
如果您有JNI的经验,那么这是一个可能的解决方案。
在Windows和Oracle Hotspot中,此代码将允许窗口在最小和最大尺寸之间调整大小,而不会闪烁或引起任何令人讨厌的JFrame-post-resize副作用。如果该代码在JFrame创建并可见后被调用,则上面使用的componentResized()中捕获调整大小事件的代码可以完全取消,因为Windows具有防止用户能够调整大小到指定的最小/最大尺寸的功能。
// 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++代码(包括标准的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);
}

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

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

// Returns the HWND for the specified component, or -1 if does not exist
public static native int getComponentHWND(Component 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;
}

注意:此解决方案在Windows和Java 1.6和1.7上可以正确运行。 - Rick Hodgin
哦,主啊...请原谅他。你可以祈祷没有人改变这些库的名称...我会把这个作为耦合的一个很好的例子。我敢说你的机器和你的代码将永远结合在一起! - Magno C

2

我不认为有一种专门用于此目的的方法。但是,您可以预设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 );

frame.setVisible(true)之前,通常需要执行frame.pack()

0
为了避免闪烁,您可以在JFrame中覆盖#setBounds方法。似乎每次调整大小都会调用它。类似这样的东西。
@Override
public void setBounds(int x, int y, int width, int height) {
    if (width == FIXED_WIDTH) {
        super.setBounds(x, y, width, height);
    }
}

对我来说起了作用。


0

不要使用setResizable(true),而是使用setResizable(false)。实际上,setResizable(false)对我很有用。它甚至禁用了最大化(变暗了图标)。

好吧,我应该更好地解释一下自己的意思。我也想让可调整大小的东西起作用。这就是为什么我会看到这个问题的原因。但最终我选择了这个,认为这会帮助OP。

我也想要可调整大小,但是如果我无法使其工作,禁用它会更好,因为它不会破坏您的内容布局。我认为这是一个解决方案。


那怎么让高度可调整呢? - Christoffer Hammarström
@ChristofferHammarström 它没有。它帮助我布置我的组件。我认为这可能对原帖有所帮助。 - Dheeraj Bhaskar
@htz 好的,我应该更好地解释一下自己。我也想让可调整大小的东西工作起来。这就是为什么我会看到这个问题。但最终我选择了这个,认为这会对 OP 有所帮助。 - Dheeraj Bhaskar
但是这怎么回答这个问题呢?@DheerajBhaskar - Dan
我也想做可调整大小的功能,但是如果我无法让它正常工作,禁用它会更好,因为这不会破坏您的内容布局。我认为这是一个解决方案。 - Dheeraj Bhaskar

0

我正好使用这段代码来实现这个目的,它可以工作(实际上是编辑了 @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);
    }
});


0
我相信大多数平台都会尊重setMaximumSizesetMinimumSize。还有setMaximizedBounds
无法工作的是添加一个监听器重置宽度。线程问题使它看起来不美观。如果您有PL&F装饰窗口(不受Windows PL&F支持),则可以对其进行修改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接