Java JWindow-始终在顶部,但在系统栏下方?

Java JWindow-始终在顶部,但在系统栏下方?,java,swing,taskbar,always-on-top,jwindow,Java,Swing,Taskbar,Always On Top,Jwindow,我一直在制作一个监控远程系统的程序,并在屏幕的一个角落(用户首选项)显示非侵入性警报,以提醒用户远程系统中的更改。为了做到这一点,我使用了一个JWindow,这样我可以为更重要的警报产生脉冲效果,以吸引用户的注意。我还有一个警报,可以从屏幕外滚动到屏幕上 我遇到的问题是,如果我没有将这些警报设置为始终在顶部,它们不会始终显示,但如果我将它们设置为始终在顶部,滚动选项也会在任务栏上方显示。是否有任何方法可以强制它显示在所有其他程序上(不需要应用全屏程序),但显示在任务栏下方 编辑:以下是我在屏幕上

我一直在制作一个监控远程系统的程序,并在屏幕的一个角落(用户首选项)显示非侵入性警报,以提醒用户远程系统中的更改。为了做到这一点,我使用了一个JWindow,这样我可以为更重要的警报产生脉冲效果,以吸引用户的注意。我还有一个警报,可以从屏幕外滚动到屏幕上

我遇到的问题是,如果我没有将这些警报设置为始终在顶部,它们不会始终显示,但如果我将它们设置为始终在顶部,滚动选项也会在任务栏上方显示。是否有任何方法可以强制它显示在所有其他程序上(不需要应用全屏程序),但显示在任务栏下方

编辑:以下是我在屏幕上/屏幕下滚动JWindow的代码:

Edit2:更新代码以显示我加入了NESPowerGlove的答案:

public void scrollOn() {
    //Get the normal screen area minus taskbar
    Insets scnMax = Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration());
    int taskBar = scnMax.bottom; //Bottom of the normal window area
    int x = screenSize.width - getWidth(); //Horizontal start point of the window
    int yEnd = screenSize.height - taskBar - getHeight(); //where the window will stop
    int yStart = screenSize.height; //Vertical start point of the window
    setLocation(x,yStart); //set window to start location
    int current = yStart; //windows current location
    newHeight = yStart - current; //Set the newHeight field to the clipping start height
    while(current > yEnd) { //loop while window is still enroute to final destination
        current-=2; //increments to move the window, in pixels
        newHeight = yStart - current; //Update the newHeight field to clip the window appropriately based on position
        setLocation(x,current); //move the window to the next position
        try {
            Thread.sleep(30);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
//This is basically the reverse of the scrollOn() method
public void scrollOff() {
    Insets scnMax = Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration());
    int taskBar = scnMax.bottom;
    int x = screenSize.width - getWidth();
    int yEnd = screenSize.height - taskBar;
    int yStart = this.getBounds().y;
    setLocation(x,yStart);
    int current = yStart;
    newHeight = this.getBounds().height;
    while(current < yEnd) {
        current+=2;
        newHeight = yEnd - current;
        setLocation(x,current);
        try {
            Thread.sleep(30);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //Tells the system the next alert can be triggered
    //This prevents screen clutter from multiple alerts by setting up a queue
    Main.alertControl.setAlertActive(false); 
}

通过计算窗口框架显示在其中的常用区域的边界,可以避免在任务栏(或其他类似区域)上显示JWindow:

Rectangle maxBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
编辑:问题作者在本答案的评论部分提到的动画问题的更多代码,他希望也包括在答案中:


有了这个,我认为你可以使框架不装饰(setUndercorated(true)),然后使背景完全透明,然后慢慢增加你在背景中绘制的矩形的高度,最终在整个窗口中着色

。在您的情况下,更改:

setShape(new Ellipse2D.Double(0,0,getWidth(),getHeight()));
to(并经常调用,通过首先更新newHeightOfDisplay来缓慢更新矩形的位置)


我不确定这是否是一种推荐做法,但以下内容符合您的要求:

while(tillYouWantToDisplay) {
    window.setAlwaysOnTop(true);
    window.setAlwaysOnTop(false);
    delay(delayTime);   // You have to write this method using sleep()
                        // delayTime may be about 500ms
}
window.dispose();
您可能需要将上述代码放在一个线程中

我已经在下面编写了快速演示代码来说明我的意思(只需运行它即可查看):

导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.GraphicsEnvironment;
导入java.awt.Point;
导入java.awt.Rectangle;
导入javax.swing.JLabel;
导入javax.swing.JWindow;
公共类测试程序扩展JWindow{
公共静态void main(字符串[]args)引发异常{
TestProgram window=新的TestProgram();
window.setVisible(true);
维度windowDim=window.getSize();
int步数=20;
对于(int i=0;i
Hmm,那么基本上,你是说当窗口位于任务栏下方时屏蔽它,然后让它从任务栏下方显示出来?按照我现在的方式,它只是从屏幕外开始滚动。我还没有真正弄清楚屏蔽窗口的某些部分。我是说不要使JWindow的边界超出getMaximumWindowBounds()返回的边界。您可以通过几种方式使应用程序看起来像是从任务栏下方向上滚动。一种方法是,假设您正在使用一个已经没有边框或标题栏的未装饰窗口,使其始终位于任务栏上方,但慢慢增加背景开始不透明的高度,同样的高度计算可以用于填充GUI第一个面板显示的高度,以便GUI跟踪最新的不透明高度。另一种方法(在下一篇评论中继续)另一种方法是简单地让你的JWindow以1的高度开始,然后慢慢地增加它的高度和y位置(比如,用SwingTimer每x毫秒增加1个像素,同样的计时器机制也可以用于第一个建议);我只是不知道如何在窗户上做部分不透明的部分。该窗口将使用
BoarderLayout
或自定义定位,使用多个图像构建自定义“外观和感觉”;静态角和动态可伸缩的边以及顶部/底部/中心,以便调整其大小以适应警报消息的大小。我认为您可以使框架不装饰(SetUn装饰(true)),然后慢慢地增加你在背景中绘制的矩形的高度,它最终会在整个窗口中着色。我实际上已经考虑过这一点,但它有点违背了让窗口滚动到屏幕上的目的。滚动的主要目的是通过移动来吸引用户的眼球。嗯,编辑确实有效,尽管有点闪烁(在上/下之间)。投票赞成做OP中要求的事情,但我更喜欢NESPowerGlove的方法,因为它比我最初要求的方法有更专业的感觉;而且没有闪烁。不过,我可能会在其他地方使用你的方法。谢谢你的意见!哦,旁注:一定要添加一个commo
setShape(new Rectangle2D.Double(0, getHeight() - newHeightOfDisplay, getWidth(), newHeightOfDisplay));
while(tillYouWantToDisplay) {
    window.setAlwaysOnTop(true);
    window.setAlwaysOnTop(false);
    delay(delayTime);   // You have to write this method using sleep()
                        // delayTime may be about 500ms
}
window.dispose();
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.JLabel;
import javax.swing.JWindow;

public class TestProgram extends JWindow {

    public static void main(String[] args) throws Exception {
        TestProgram window = new TestProgram();
        window.setVisible(true);

        Dimension windowDim = window.getSize();
        int steps = 20;
        for (int i = 0; i < steps; i++) {
            window.setAlwaysOnTop(true);
            window.setAlwaysOnTop(false);
            Point p = window.getLocation();
            window.setLocation(p.x, p.y - windowDim.height / steps);
            Thread.sleep(100);
        }
        for (int i = 0; i < 10; i++) {
            window.setAlwaysOnTop(true);
            window.setAlwaysOnTop(false);
            Thread.sleep(100);
        }
        for (int i = 0; i < steps; i++) {
            window.setAlwaysOnTop(true);
            window.setAlwaysOnTop(false);
            Point p = window.getLocation();
            window.setLocation(p.x, p.y + windowDim.height / steps);
            Thread.sleep(100);
        }
        window.dispose();
    }

    public TestProgram() {
        setSize(200, 100);
        Rectangle scrDim = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
        setLocation(scrDim.x + scrDim.width - getSize().width, scrDim.y + scrDim.height);

        JLabel msg = new JLabel("Your Message");
        msg.setHorizontalAlignment(JLabel.CENTER);
        msg.setVerticalAlignment(JLabel.CENTER);
        getContentPane().add(msg);
        getContentPane().setBackground(Color.red);
    }
}