本来在网上找了一个JPopupButton【@author SunKing】,但是实际使用的时候,无法满足L&F效果,在JGoodies Looks下无法正常显示。
期间还在网络找了一个JPopupToggleButton【@author Alexander Wenckus】,但是感觉过于简单,也不够满意。
于是只好自己重写一个。
以下为相关代码:
注意: 勿遗落最后的/name/xio/util/swing/toolbar-buttonarrow.png文件。
name.xio.util.swing.JPopupButton
package name.xio.util.swing; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Insets; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.AbstractAction; import javax.swing.AbstractButton; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.ButtonModel; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JToolBar; import javax.swing.MenuElement; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.WindowConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import name.xio.util.swing.icon.CompositeIcon; import name.xio.util.swing.icon.HTextIcon; import com.by.yb.util.Utilities; import com.jgoodies.looks.LookUtils; import com.jgoodies.looks.plastic.PlasticXPLookAndFeel; import com.jgoodies.looks.plastic.theme.ExperienceBlue; import com.jgoodies.looks.windows.WindowsLookAndFeel; /** * 弹出菜单按钮 * @author xio * */ public class JPopupButton extends JButton { private static final long serialVersionUID = -6783978058195706887L; /** * 弹出菜单 */ private JPopupMenu menu = new JPopupMenu(); /** * 按钮点击事件,与菜单中的第几项绑定 */ private int attachActionOnPopupMenuIndex = -1; /** * 是否显示箭头部分的分割线 */ private boolean showSeparator = false; public final static int NARROW_WIDTH = 11; public JPopupButton(Icon icon, JPopupMenu menu) { this(null, icon, menu); } public JPopupButton(String text, JPopupMenu menu) { this(text, null, menu); } public JPopupButton(String text, Icon icon, JPopupMenu menu) { initView(text, icon, menu); } /** * 初始化菜单按钮的视图 * @param text * @param icon * @param menu */ private void initView(String text, Icon icon, JPopupMenu menu) { //1.按钮绘制 this.setFocusable(false); this.setText(null); HTextIcon hTextIcon = new HTextIcon(this, text, 10); if (icon != null) { CompositeIcon commonButtonIcon = new CompositeIcon(icon, hTextIcon, CompositeIcon.LEFT); CompositeIcon popupButtonIcon = new CompositeIcon(commonButtonIcon, new ImageIcon(JPopupButton.class .getResource("toolbar-buttonarrow.png")), CompositeIcon.LEFT, 2, 0); this.setIcon(popupButtonIcon); } else { CompositeIcon popupButtonIcon = new CompositeIcon(hTextIcon, new ImageIcon(JPopupButton.class .getResource("toolbar-buttonarrow.png")), CompositeIcon.LEFT, 2, 0); this.setIcon(popupButtonIcon); } //this.setMargin(new Insets()); this.menu = menu; //2.事件监听 //Rollover监听 this.addChangeListener(new RolloverChangeListener()); //添加按钮鼠标事件监听 PopupButtonListener popupButtonListener = new PopupButtonListener(); this.addMouseMotionListener(popupButtonListener); this.addMouseListener(popupButtonListener); //添加菜单事件监听 if (menu != null) { menu.addPopupMenuListener(popupButtonListener); } //初始按钮事件绑定 clearAttachActionOnPopupMenu(); } /** * 清空按钮绑定事件 */ public void clearAttachActionOnPopupMenu() { attachActionOnPopupMenu(-1); } /** * 按钮行为绑定为弹出菜单第一项 */ public void attachDefaultActionOnPopupMenu() { attachActionOnPopupMenu(0); } /** * 按钮的行为绑定为弹出菜单 * @param index */ public void attachActionOnPopupMenu(int index) { if (menu == null) { attachActionOnPopupMenuIndex = -1; } else { MenuElement[] menuElements = menu.getSubElements(); if ((index < 0) || (Utilities.isEmpty(menuElements)) || (index >= menuElements.length)) { attachActionOnPopupMenuIndex = -1; } else { attachActionOnPopupMenuIndex = index; } } } /** * @return Returns the menu. */ public JPopupMenu getMenu() { return menu; } private void showMenu() { if (menu == null) { return; } Point locate = locateMenu(); menu.show(this, locate.x, locate.y); } private void showSeparator(boolean b) { showSeparator = b; this.repaint(); } /** * 按钮左部触发 */ public void onClick() { //点击位置为箭头位置 boolean mouseInNarrow = isMouseInNarrow(); if (mouseInNarrow) { onClickNarrow(); } else { if (attachActionOnPopupMenuIndex < 0) { onClickNarrow(); } else { MenuElement[] menuElements = menu.getSubElements(); ((AbstractButton) menuElements[attachActionOnPopupMenuIndex]).doClick(); } } } /** * 按钮箭头部触发 */ private void onClickNarrow() { showMenu(); } /** * 菜单位置 * @return */ protected Point locateMenu() { Point locate = new Point((int) getAlignmentX(), (int) getAlignmentY() + (getHeight() == 0 ? getPreferredSize().height : getHeight())); return locate; } public void paint(Graphics g) { super.paint(g); //绘制分离线 if (showSeparator) { Color oldColor = g.getColor(); Insets insets = this.getInsets(); int width = getWidth(); int height = getHeight(); Icon icon = this.getIcon(); //int x = icon == null ? (width - NARROW_WIDTH) : (mrgin.left - insets.left + icon.getIconWidth() - NARROW_WIDTH); int x = icon == null ? (width - NARROW_WIDTH) : (insets.left + icon.getIconWidth() - NARROW_WIDTH); int y = 0; // Button.light // Button.shadow // Button.darkShadow // Button.highlight //g.setColor(new Color(216, 214, 207)); g.setColor(UIManager.getColor("Button.shadow")); g.drawLine(x, y + 1, x, y + height - 3); //g.setColor(new Color(250, 250, 248)); g.setColor(UIManager.getColor("Button.highlight")); g.drawLine(x + 1, y + 1, x + 1, y + height - 3); g.setColor(oldColor); } } /** * 当前鼠标是否在按钮上 * @return */ public boolean isMouseOver() { return this.getMousePosition() != null; } /** * 鼠标位置是否在箭头部分 * @return */ public boolean isMouseInNarrow() { Point position = this.getMousePosition(); if (position == null) { return false; } else { return isMouseInNarrow(position); } } /** * 鼠标位置是否在箭头部分 * @param position * @return */ public boolean isMouseInNarrow(Point position) { Insets insets = this.getInsets(); Icon icon = this.getIcon(); int width = this.getWidth(); int height = this.getHeight(); //int narrowFromX = icon == null ? (width - NARROW_WIDTH) : (mrgin.left - insets.left + icon.getIconWidth() - NARROW_WIDTH); int narrowFromX = icon == null ? (width - NARROW_WIDTH) : (insets.left + icon.getIconWidth() - NARROW_WIDTH); int narrowFromY = 0; int narrowEndX = width; int narrowEndY = height; int eventX = (int) position.getX(); int eventY = (int) position.getY(); return ((narrowFromX <= eventX) && (eventX <= narrowEndX)) && ((narrowFromY <= eventY) && (eventY <= narrowEndY)); } /** * 按钮Rollover监听 * @author xio * */ class RolloverChangeListener implements ChangeListener { public void stateChanged(ChangeEvent e) { ButtonModel buttonModel = JPopupButton.this.getModel(); showSeparator(buttonModel.isRollover() || buttonModel.isPressed()); } } /** * 按钮和菜单的事件监听 * @author xio * */ class PopupButtonListener extends MouseAdapter implements PopupMenuListener { public void mouseEntered(MouseEvent e) { //防止部分L&F未设置Rollover JPopupButton.this.getModel().setRollover(true); } public void mouseExited(MouseEvent e) { //防止部分L&F未设置Rollover JPopupButton.this.getModel().setRollover(false); showSeparator(false); } public void mouseClicked(MouseEvent e) { JPopupButton.this.onClick(); } public void popupMenuCanceled(PopupMenuEvent e) { } public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { //菜单不可见时,如果鼠标还在按钮上,设置Rollover状态,以便按钮的视图显示为Rollover if (isMouseOver()) { JPopupButton.this.getModel().setRollover(true); } } public void popupMenuWillBecomeVisible(PopupMenuEvent e) { //菜单显示时,修改按钮Rollover状态 JPopupButton.this.getModel().setRollover(false); } } public static void main(String[] args) { try { //不显示ToolBar的边界 UIManager.put("ToolBar.border", BorderFactory.createEmptyBorder()); if (LookUtils.IS_LAF_WINDOWS_XP_ENABLED) { UIManager.setLookAndFeel(new WindowsLookAndFeel()); } else { PlasticXPLookAndFeel.setCurrentTheme(new ExperienceBlue()); UIManager.setLookAndFeel(new PlasticXPLookAndFeel()); } // PlasticXPLookAndFeel.setCurrentTheme(new ExperienceBlue()); // UIManager.setLookAndFeel(new PlasticXPLookAndFeel()); } catch (UnsupportedLookAndFeelException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } JFrame frame = new JFrame("JPopupButton"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setSize(400, 320); //SwingUtils.locateCenterOnScreen(frame); class DemoAction extends AbstractAction { private static final long serialVersionUID = 5232174589593930544L; public DemoAction(String id) { super.putValue(Action.NAME, "Demo JPopupButton " + id); } public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog((Component) e.getSource(), super.getValue(Action.NAME)); } } JPopupMenu popup = new JPopupMenu("PopupMenu"); popup.add(new DemoAction("0")); popup.add(new DemoAction("1")); popup.add(new DemoAction("2")); JPopupButton btt1 = new JPopupButton("中文文字", null, popup); JPopupButton btt2 = new JPopupButton("中文文字", null, popup); btt2.attachDefaultActionOnPopupMenu(); JPopupButton btt3 = new JPopupButton("中文文字", UIManager.getIcon("FileView.computerIcon"), popup); btt3.attachActionOnPopupMenu(2); JToolBar toolbar = new JToolBar(); toolbar.add(btt1); toolbar.add(btt2); toolbar.add(btt3); toolbar.add(new JButton("中文文字", UIManager.getIcon("FileView.computerIcon"))); toolbar.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 3)); frame.getContentPane().add(toolbar, BorderLayout.NORTH); frame.setVisible(true); } }
name.xio.util.swing.icon.CompositeIcon
package name.xio.util.swing.icon; import java.awt.Component; import java.awt.Graphics; import javax.swing.Icon; import javax.swing.SwingConstants; /** CompositeIcon is an Icon implementation which draws two icons with a specified relative position: LEFT, RIGHT, TOP, BOTTOM specify how icon1 is drawn relative to icon2 CENTER: icon1 is drawn first, icon2 is drawn over it and with horizontal and vertical orientations within the alloted space It's useful with VTextIcon when you want an icon with your text: if icon1 is the graphic icon and icon2 is the VTextIcon, you get a similar effect to a JLabel with a graphic icon and text * @from http://www.macdevcenter.com/pub/a/mac/2002/03/22/vertical_text.html?page=last&x-order=date * @changedBy xio */ public class CompositeIcon implements Icon, SwingConstants { Icon fIcon1, fIcon2; int fPosition, fHorizontalOrientation, fVerticalOrientation; int widthOffset, heightOffset; /** Create a CompositeIcon from the specified Icons, using the default relative position (icon1 above icon2) and orientations (centered horizontally and vertically) */ public CompositeIcon(Icon icon1, Icon icon2) { this(icon1, icon2, TOP); } /** Create a CompositeIcon from the specified Icons, using the specified relative position and default orientations (centered horizontally and vertically) */ public CompositeIcon(Icon icon1, Icon icon2, int position) { this(icon1, icon2, position, CENTER, CENTER, (position == LEFT || position == RIGHT) ? 2 : -7, (position == LEFT || position == RIGHT) ? 0 : 6); } public CompositeIcon(Icon icon1, Icon icon2, int position, int widthOffset, int heightOffset) { this(icon1, icon2, position, CENTER, CENTER, widthOffset, heightOffset); } /** Create a CompositeIcon from the specified Icons, using the specified relative position and orientations */ public CompositeIcon(Icon icon1, Icon icon2, int position, int horizontalOrientation, int verticalOrientation, int widthOffset, int heightOffset) { fIcon1 = icon1; fIcon2 = icon2; fPosition = position; this.widthOffset = widthOffset; this.heightOffset = heightOffset; fHorizontalOrientation = horizontalOrientation; fVerticalOrientation = verticalOrientation; } /** * Draw the icon at the specified location. Icon implementations * may use the Component argument to get properties useful for * painting, e.g. the foreground or background color. */ public void paintIcon(Component c, Graphics g, int x, int y) { int width = getIconWidth(); int height = getIconHeight(); if (fPosition == LEFT || fPosition == RIGHT) { Icon leftIcon, rightIcon; if (fPosition == LEFT) { leftIcon = fIcon1; rightIcon = fIcon2; } else { leftIcon = fIcon2; rightIcon = fIcon1; } // "Left" orientation, because we specify the x position paintIcon(c, g, leftIcon, x, y, width, height, LEFT, fVerticalOrientation); paintIcon(c, g, rightIcon, x + leftIcon.getIconWidth(), y, width, height, LEFT, fVerticalOrientation); } else if (fPosition == TOP || fPosition == BOTTOM) { Icon topIcon, bottomIcon; if (fPosition == TOP) { topIcon = fIcon1; bottomIcon = fIcon2; } else { topIcon = fIcon2; bottomIcon = fIcon1; } // "Top" orientation, because we specify the y position paintIcon(c, g, topIcon, x, y, width, height, fHorizontalOrientation, TOP); paintIcon(c, g, bottomIcon, x, y + topIcon.getIconHeight(), width, height, fHorizontalOrientation, TOP); } else { paintIcon(c, g, fIcon1, x, y, width, height, fHorizontalOrientation, fVerticalOrientation); paintIcon(c, g, fIcon2, x, y, width, height, fHorizontalOrientation, fVerticalOrientation); } } /* Paints one icon in the specified rectangle with the given orientations */ void paintIcon(Component c, Graphics g, Icon icon, int x, int y, int width, int height, int horizontalOrientation, int verticalOrientation) { int xIcon, yIcon; switch (horizontalOrientation) { case LEFT: xIcon = x; break; case RIGHT: xIcon = x + width - icon.getIconWidth(); break; default: xIcon = x + (width - icon.getIconWidth()) / 2; break; } switch (verticalOrientation) { case TOP: yIcon = y; break; case BOTTOM: yIcon = y + height - icon.getIconHeight(); break; default: yIcon = y + (height - icon.getIconHeight()) / 2; break; } icon.paintIcon(c, g, xIcon, yIcon); } /** * Returns the icon's width. * * @return an int specifying the fixed width of the icon. */ public int getIconWidth() { if (fPosition == LEFT || fPosition == RIGHT) return fIcon1.getIconWidth() + fIcon2.getIconWidth() + widthOffset; return Math.max(fIcon1.getIconWidth(), fIcon2.getIconWidth()) + widthOffset; } /** * Returns the icon's height. * * @return an int specifying the fixed height of the icon. */ public int getIconHeight() { if (fPosition == TOP || fPosition == BOTTOM) return fIcon1.getIconHeight() + fIcon2.getIconHeight() + heightOffset; return Math.max(fIcon1.getIconHeight(), fIcon2.getIconHeight()) + heightOffset; } }
name.xio.util.swing.icon.HTextIcon
package name.xio.util.swing.icon; import java.awt.Component; import java.awt.FontMetrics; import java.awt.Graphics; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.Icon; /** * 水平文本Icon * @author xio * */ public class HTextIcon implements Icon, PropertyChangeListener { private String text; private int textWidth; private int textHeight; private int fontCharHeight; private Component fontComponent; private int marginLeft; private int marginRight; static final int MARGIN = 4; static final int MIN_TEXT_HEIGHT = 15; static final int MIN_TEXT_WIDTH = 16; public HTextIcon(Component component, String label) { this(component, label, MARGIN, MARGIN); } public HTextIcon(Component component, String label, int marginRight) { this(component, label, MARGIN, marginRight); } /** * 指定一个Component,创建水平文本Icon * @param component * @param label */ public HTextIcon(Component component, String label, int marginLeft, int marginRight) { fontComponent = component; text = label; this.marginLeft = marginLeft; this.marginRight = marginRight; calcDimensions(); fontComponent.addPropertyChangeListener(this); } /** * sets the label to the given string, updating the orientation as needed * and invalidating the layout if the size changes * @see #verifyRotation */ public void setLabel(String label) { text = label; recalcDimensions(); } /** * Checks for changes to the font on the fComponent * so that it can invalidate the layout if the size changes */ public void propertyChange(PropertyChangeEvent e) { String prop = e.getPropertyName(); if ("font".equals(prop)) { recalcDimensions(); } } /** * Calculates the dimensions. If they've changed, * invalidates the component */ void recalcDimensions() { int wOld = getIconWidth(); int hOld = getIconHeight(); calcDimensions(); if (wOld != getIconWidth() || hOld != getIconHeight()) fontComponent.invalidate(); } void calcDimensions() { FontMetrics fontMetrics = fontComponent.getFontMetrics(fontComponent.getFont()); int fontDescent = fontMetrics.getDescent(); fontCharHeight = fontMetrics.getAscent() + fontDescent; textWidth = fontMetrics.stringWidth(text) + marginLeft + marginRight; if (textWidth < MIN_TEXT_WIDTH) { textWidth = MIN_TEXT_WIDTH; } textHeight = fontCharHeight + fontDescent; if (textHeight < MIN_TEXT_HEIGHT) { textHeight = MIN_TEXT_HEIGHT; } // //强制调整尺寸 // fWidth -= 5; // fHeight += 6; } /** * 绘制文本 */ public void paintIcon(Component c, Graphics g, int x, int y) { g.setColor(c.getForeground()); g.setFont(c.getFont()); g.drawString(text, x + marginLeft, y + fontCharHeight - 2); } /** * icon宽度 */ public int getIconWidth() { return textWidth; } /** * icon高度 */ public int getIconHeight() { return textHeight; } }
/name/xio/util/swing/toolbar-buttonarrow.png: http://xio.iteye.com/upload/attachment/44097/f0b31625-ac6e-36a5-a5cd-d86bca96e72d.png
评论
1 楼
mikewang
2009-04-09
做的,不错, 在给你你加个点击记忆功能
思路
1 每次点击菜单的时候保存这个菜单的index,并且出发菜单下表变更事件
2 在JPopupButton中 监听事件, 并调用attachActionOnPopupMenu 绑定点击按钮所执行的菜单
实现:
JPopupMenu 达不到要求, 需要改造一下
JPopupButton 本部分都差不多, 就增加了一个属性监听器, 监听clickedMenuIndex, 并调用attachActionOnPopupMenu, 改变下标
思路
1 每次点击菜单的时候保存这个菜单的index,并且出发菜单下表变更事件
2 在JPopupButton中 监听事件, 并调用attachActionOnPopupMenu 绑定点击按钮所执行的菜单
实现:
JPopupMenu 达不到要求, 需要改造一下
package info.mikewang.part.test; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.util.Vector; import javax.swing.AbstractButton; import javax.swing.JPopupMenu; import javax.swing.MenuElement; class JPopupButtonMenu extends JPopupMenu { private static final long serialVersionUID = -8812143869773395718L; private int clickedMenuIndex = -1; public JPopupButtonMenu() { this(null); } public JPopupButtonMenu(String label) { super(label); addContainerListener(new XContainerListener()); } public int getClickedMenuIndex() { return clickedMenuIndex; } public AbstractButton[] getSubClickedElements() { AbstractButton result[]; Vector<AbstractButton> tmpx = new Vector<AbstractButton>(); MenuElement tmp[] = getSubElements(); for (MenuElement menuElement : tmp) { if (menuElement instanceof AbstractButton) { tmpx.add((AbstractButton) menuElement); } } result = new AbstractButton[tmpx.size()]; for (int i = 0; i < tmpx.size(); i++) { result[i] = tmpx.elementAt(i); } return result; } // ---------------------------------- class XContainerListener implements ContainerListener { @Override public void componentAdded(ContainerEvent e) { Component c = e.getChild(); if (c instanceof AbstractButton) { ((AbstractButton) c).addActionListener(new XActionListener()); } } @Override public void componentRemoved(ContainerEvent e) { } } class XActionListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { AbstractButton ab = (AbstractButton) e.getSource(); AbstractButton abs[] = getSubClickedElements(); for (int i = 0; i < abs.length; i++) { if (ab == abs[i]) { int oldClickedMenuIndex = clickedMenuIndex; clickedMenuIndex = i; firePropertyChange("clickedMenuIndex", oldClickedMenuIndex, i); break; } } } } }
JPopupButton 本部分都差不多, 就增加了一个属性监听器, 监听clickedMenuIndex, 并调用attachActionOnPopupMenu, 改变下标
private void initClickRemember() { menu.addPropertyChangeListener("clickedMenuIndex", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { Integer ii = (Integer) evt.getNewValue(); attachActionOnPopupMenu(ii.intValue()); } }); }
相关推荐
2006/01/20 修正了JPopupButton在XP风格下呈两个按钮样子的BUG 对JFontDialog进行了部分修改 2006/03/08 从JDatePicker提出来一个组件JCalendarPanel日期选择面板 并修改了JDatePicker的设计方式 2006/03/23 ...
只能输入0~255数字的IP地址 JListChooser 列表选择对话框 JNumberField 数字输入框,可限制小数位数,数字最大长度,最大最小能输入的数字 JPopupButton 带下拉菜单的工具栏按钮 JStatusBar 模拟Windows的...
少儿编程scratch项目源代码文件案例素材-和朋友们一起跳伞.zip
少儿编程scratch项目源代码文件案例素材-掉箱子.zip
少儿编程scratch项目源代码文件案例素材-格斗.zip
内容概要:本文详细介绍了三种主流的深度强化学习算法-DDPG、TD3和SAC在机器人控制领域的应用,特别是在MuJoCo仿真环境中的实现细节。首先解释了每个算法的基本原理及其独特之处,如DDPG的确定性策略生成器、TD3的双Critic网络以及SAC的熵最大化机制。接着深入探讨了这些算法的具体代码实现,包括Actor和Critic网络的设计、损失函数的构建以及一些实用的调参技巧。此外,还分享了许多实战经验和常见陷阱,如正确处理done信号、添加动作变化量惩罚项、观测空间的归一化等。 适合人群:对深度强化学习有一定了解并希望深入了解其在机器人控制领域应用的研究人员和技术爱好者。 使用场景及目标:帮助读者掌握如何将DDPG、TD3和SAC应用于具体的机器人控制任务中,提高算法性能,解决实际问题。同时,也为进一步研究提供了宝贵的实践经验。 其他说明:文中不仅提供了详细的理论讲解,还附带了大量的代码片段,便于读者理解和实践。对于想要深入理解这些算法内部运作机制的人来说,是一份不可多得的学习资料。
文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 编译闪电般迅速,并发性能卓越,部署轻松简单!Go 语言以极简设计理念和出色工程性能,成为云原生时代的首选编程语言。从 Docker 到 Kubernetes,全球顶尖科技企业都在采用 Go。点击了解 Go 语言的核心优势、实战窍门和未来走向,开启高效编程的全新体验!
少儿编程scratch项目源代码文件案例素材-地图制作器.zip
【资源说明】 1.项目代码功能经验证ok,确保稳定可靠运行。欢迎下载使用!在使用过程中,如有问题或建议,请及时私信沟通。 2.主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 本文介绍了基于QEM(Quadric Error Metrics,二次误差度量)的优化网格简化算法的C和C++实现源码及其相关文档。这一算法主要应用于计算机图形学领域,用于优化三维模型的多边形数量,使之在保持原有模型特征的前提下实现简化。简化的目的是为了提高渲染速度,减少计算资源消耗,以及便于网络传输等。 本项目的核心是网格简化算法的实现,而QEM作为该算法的核心,是一种衡量简化误差的数学方法。通过计算每个顶点的二次误差矩阵来评估简化操作的误差,并以此来指导网格简化过程。QEM算法因其高效性和准确性在计算机图形学中广泛应用,尤其在实时渲染和三维打印领域。 项目代码包含C和C++两种语言版本,这意味着它可以在多种开发环境中运行,增加了其适用范围。对于计算机相关专业的学生、教师和行业从业者来说,这个项目提供了丰富的学习和实践机会。无论是作为学习编程的入门材料,还是作为深入研究计算机图形学的项目,该项目都具有实用价值。 此外,项目包含的论文文档为理解网格简化算法提供了理论基础。论文详细介绍了QEM算法的原理、实施步骤以及与其他算法的对比分析。这不仅有助于加深对算法的理解,也为那些希望将算法应用于自己研究领域的人员提供了参考资料。 资源说明文档强调了项目的稳定性和可靠性,并鼓励用户在使用过程中提出问题或建议,以便不断地优化和完善项目。文档还提醒用户注意查看,以获取使用该项目的所有必要信息。 项目的文件名称列表中包含了加水印的论文文档、资源说明文件和实际的项目代码目录,后者位于名为Mesh-Simplification-master的目录下。用户可以将这些资源用于多种教学和研究目的,包括课程设计、毕业设计、项目立项演示等。 这个项目是一个宝贵的资源,它不仅提供了一个成熟的技术实现,而且为进一步的研究和学习提供了坚实的基础。它鼓励用户探索和扩展,以期在计算机图形学领域中取得更深入的研究成果。
【资源说明】 1.项目代码功能经验证ok,确保稳定可靠运行。欢迎下载使用!在使用过程中,如有问题或建议,请及时私信沟通。 2.主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 本文介绍了基于QEM(Quadric Error Metrics,二次误差度量)的优化网格简化算法的C和C++实现源码及其相关文档。这一算法主要应用于计算机图形学领域,用于优化三维模型的多边形数量,使之在保持原有模型特征的前提下实现简化。简化的目的是为了提高渲染速度,减少计算资源消耗,以及便于网络传输等。 本项目的核心是网格简化算法的实现,而QEM作为该算法的核心,是一种衡量简化误差的数学方法。通过计算每个顶点的二次误差矩阵来评估简化操作的误差,并以此来指导网格简化过程。QEM算法因其高效性和准确性在计算机图形学中广泛应用,尤其在实时渲染和三维打印领域。 项目代码包含C和C++两种语言版本,这意味着它可以在多种开发环境中运行,增加了其适用范围。对于计算机相关专业的学生、教师和行业从业者来说,这个项目提供了丰富的学习和实践机会。无论是作为学习编程的入门材料,还是作为深入研究计算机图形学的项目,该项目都具有实用价值。 此外,项目包含的论文文档为理解网格简化算法提供了理论基础。论文详细介绍了QEM算法的原理、实施步骤以及与其他算法的对比分析。这不仅有助于加深对算法的理解,也为那些希望将算法应用于自己研究领域的人员提供了参考资料。 资源说明文档强调了项目的稳定性和可靠性,并鼓励用户在使用过程中提出问题或建议,以便不断地优化和完善项目。文档还提醒用户注意查看,以获取使用该项目的所有必要信息。 项目的文件名称列表中包含了加水印的论文文档、资源说明文件和实际的项目代码目录,后者位于名为Mesh-Simplification-master的目录下。用户可以将这些资源用于多种教学和研究目的,包括课程设计、毕业设计、项目立项演示等。 这个项目是一个宝贵的资源,它不仅提供了一个成熟的技术实现,而且为进一步的研究和学习提供了坚实的基础。它鼓励用户探索和扩展,以期在计算机图形学领域中取得更深入的研究成果。
少儿编程scratch项目源代码文件案例素材-鸽子飞行模拟器.zip
少儿编程scratch项目源代码文件案例素材-仿作马里奥冒险.zip
文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 编译闪电般迅速,并发性能卓越,部署轻松简单!Go 语言以极简设计理念和出色工程性能,成为云原生时代的首选编程语言。从 Docker 到 Kubernetes,全球顶尖科技企业都在采用 Go。点击了解 Go 语言的核心优势、实战窍门和未来走向,开启高效编程的全新体验!
内容概要:本文详细介绍了如何利用Carsim和Simulink进行线控转向系统的联合仿真。首先解释了线控转向系统的基本概念及其重要性,特别是在自动驾驶领域的应用前景。接着阐述了Carsim和Simulink的集成方法,包括环境配置、模型对接、S函数接口的具体实现步骤以及注意事项。文中还提供了转向控制算法的实例,如PID控制器的设计思路和参数选择依据,并强调了数据同步的重要性,分享了一些实用的小技巧,如通过XY Graph监测转向性能、确保仿真步长的一致性等。最后指出,这套仿真平台非常适合用于验证各种高级驾驶辅助系统的控制算法,能够显著提高开发效率并降低成本。 适合人群:汽车电子工程师、自动驾驶研究人员、控制系统开发者。 使用场景及目标:适用于需要快速迭代和验证线控转向及相关自动驾驶控制算法的研发阶段,帮助工程师们在虚拟环境中完成大量实验,减少实物测试的风险和成本。 其他说明:文中提到的技术细节对于理解和实施线控转向系统的联合仿真非常关键,尤其是关于数据同步和控制算法优化的部分。此外,作者还分享了许多个人经验教训,有助于避免常见的错误和技术陷阱。
内容概要:本文详细介绍了如何使用LabVIEW与ABB设备进行集成,主要涉及通过OPC UA协议获取ABB设备的日志、设备信息、速度及状态等关键数据。文中提供了具体的LabVIEW代码示例,涵盖了通信配置、数据解析、状态监测、日志抓取等多个方面。此外,还分享了许多实际操作中的经验和技巧,如TCP/IP通信、JSON数据处理、错误处理机制以及数据可视化的最佳实践。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些熟悉LabVIEW并希望深入了解ABB设备集成的人群。 使用场景及目标:适用于需要对ABB设备进行实时监控和数据分析的工程项目。具体目标包括:① 实现与ABB设备的高效通信;② 获取并解析设备的关键数据;③ 监控设备状态并记录日志;④ 提升系统的可靠性和稳定性。 其他说明:本文不仅提供理论指导,还结合了大量的实战案例和代码片段,帮助读者更好地理解和应用相关技术。
毕业设计-基于JavaSE实现魂动罗小游戏 1. Demo简介 本demo仿制了一个魂斗罗小游戏,纯JavaSE实现。 [image] 1.1 技术应用 ● 键盘控制 ● 图片显示 ● 音频播放 ● 多线程控制 2. demo使用 拿到源码后进入MainFrame主类中运行: public static void main(String[] args) { new Thread(new MainFrame()).start(); } [image] 按照右侧使用说明控制,无限生命。 3. 总结 简单的JavaSE小demo,需要练手的同学拿去看看。 [image]
内容概要:本文详细介绍了如何使用西门子PLC(如S7-1200/1500)通过Modbus协议与第三方仪表进行数据读写。主要内容涵盖硬件接线、Modbus库函数的正确使用、常见错误及其解决方法、性能优化技巧以及调试建议。文中强调了地址转换、字节顺序、超时设置等方面的具体操作和注意事项,并提供了多个代码示例来帮助理解和实施。 适合人群:从事工业自动化领域的工程师和技术人员,特别是那些需要将西门子PLC与其他品牌仪表集成在一起工作的专业人士。 使用场景及目标:适用于需要在工业环境中实现PLC与各种传感器、变送器和其他智能设备之间的可靠通信的场合。目标是确保数据传输的准确性、稳定性和效率,减少调试时间和成本。 其他说明:作者分享了许多基于实际项目的宝贵经验教训,提醒读者注意一些容易忽视但可能导致严重问题的小细节。此外,还提供了一些实用工具和方法用于辅助开发和维护工作。
内容概要:本文详细介绍了使用MATLAB模拟8DPSK(八进制差分相移键控)信号在AWGN(加性白高斯噪声)信道下的误码率(BER)和误比特率(SER)性能。文中通过具体代码展示了从生成随机二进制序列、调制、加入噪声、解调到最后计算误码率的完整流程,并将仿真结果与理论值进行了对比。同时,文章还讨论了一些常见的陷阱和技术要点,如相位偏移、格雷编码的应用以及信噪比(Eb/N0)的正确转换方法。 适合人群:具有一定MATLAB编程基础和数字通信基础知识的研究人员、工程师和学生。 使用场景及目标:适用于希望深入了解8DPSK调制特性及其在AWGN信道中性能的人群。通过本实验,读者能够掌握8DPSK的基本原理、MATLAB仿真技巧以及误码率分析的方法。 其他说明:文章提供了详细的代码片段和解释,帮助读者更好地理解和复现实验结果。此外,还提到了一些提高仿真实验效率的小技巧,如使用并行计算加速仿真过程。
少儿编程scratch项目源代码文件案例素材-赌注和梯子.zip
内容概要:本文详细介绍了如何利用信捷XD5控制器和威纶触摸屏编写高效的六轴机械手控制程序。主要内容涵盖系统概述、程序编写步骤、代码分析、实际应用效果等方面。文中强调了系统的初始化、通信参数配置、运动控制、调试日志输出等关键功能模块的设计思路和技术要点。此外,还展示了程序的实际应用案例及其优势,如高可靠性、操作便捷性和良好的扩展性。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对六轴机械手控制系统感兴趣的读者。 使用场景及目标:①掌握信捷XD5控制器和威纶触摸屏的联合使用方法;②理解六轴机械手控制程序的编写流程和关键技术;③提高六轴机械手在实际生产中的稳定性和效率。 其他说明:本文不仅提供了详细的代码示例和注释,还分享了许多实际应用中的经验和技巧,有助于读者更好地理解和应用相关技术。